mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-08 11:58:11 +08:00
Port frontend from Vue to Svelte (WIP in separate folder, many bugs) (#964)
* Make `tauri build` just work * Move folder: frontend/wasm -> wasm * Create SvelteKit project with 'npx create-svelte' * Move wasm-communication into seperate npm package * Use wasm-pack directly and pack package.json * Got it to work * Add primitive build script for wasm npm module * Fix wasm build script (python) * Clean up glue code * Rewrite wasm build script in node.js * Add serde-reflection to trace types * Add traced types * Generate typescript (.d.ts) from Rust types * Update .d.ts * Finalize TS types * Add script to update .d.ts * Add watch command to build wasm-bindgen * Make wasm work again * Add sass; fix build script for windows * Describe requirement for wasm-pack * Add license * Copy and reorganize vue components * translate LayoutCol.vue * Split app.scss into pieces * Translate LayoutRow.svelte * Rename scss files * Fix compile issues on Windows * WIP port TitleBar * Support classes for LayoutCol/Row * Restructure based on Vue codebase * Port all components in window folder * Port FloatingMenu * Port Document panel component * Update readme after folder move * Update typegen: print discriminant by default * Update typegen: Merge from branch 'tailwind' 4f14fedb Fixes bigint & bytes * Made Vue/webpack/eslint to accept wasm package at new location This is quite a hack. Those two packages are both named the same. Yes, it's an npm package inside another npm package. - frontend/src/wasm-communication/ - frontend-svelte/glue/ 'wasm/pkg/index.js' imports the correct one registered when linking. * Port LayerTree * Port NodeGraph * Port Properties * Port components in /floating-menus * Finish porting all Vue -> Svelte components * Change import prefix * Revert type generation * Revert moved wasm folder * Revert all of @locriacyber's work on this branch - Remove Vite and restore Webpack - Remove SvelteKit - Remove everything except the components I ported to Svelte - Restore all frontend files from Vue code, now altered for Svelte * Convert Vue's 'reactive' and 'provide' to Svelte's stores and contexts * Fix event emitting and bi-di data flow * Undo removal of 'update:' events * Fix 'update:' event dispatching * Fix usage in parent of bi-di component props * Fix component typing, more progress towards no errors * The page builds and opens! * Add loading spinner and remove postcss dependency * Make the basics of document editing work * Fix rebase history Co-authored-by: Locria Cyber <74560659+locriacyber@users.noreply.github.com>
This commit is contained in:
co-authored by
Locria Cyber
parent
01853fe4b7
commit
5619d44300
@@ -0,0 +1,300 @@
|
||||
/* eslint-disable import/first */
|
||||
|
||||
// Graphics
|
||||
import GraphiteLogotypeSolid from "@/../assets/graphics/graphite-logotype-solid.svg";
|
||||
|
||||
const GRAPHICS = {
|
||||
GraphiteLogotypeSolid: { svg: GraphiteLogotypeSolid, size: undefined },
|
||||
} as const;
|
||||
|
||||
// 12px Solid
|
||||
import Add from "@/../assets/icon-12px-solid/add.svg";
|
||||
import Checkmark from "@/../assets/icon-12px-solid/checkmark.svg";
|
||||
import CloseX from "@/../assets/icon-12px-solid/close-x.svg";
|
||||
import DropdownArrow from "@/../assets/icon-12px-solid/dropdown-arrow.svg";
|
||||
import Edit from "@/../assets/icon-12px-solid/edit.svg";
|
||||
import Empty12px from "@/../assets/icon-12px-solid/empty-12px.svg";
|
||||
import FullscreenEnter from "@/../assets/icon-12px-solid/fullscreen-enter.svg";
|
||||
import FullscreenExit from "@/../assets/icon-12px-solid/fullscreen-exit.svg";
|
||||
import Grid from "@/../assets/icon-12px-solid/grid.svg";
|
||||
import Info from "@/../assets/icon-12px-solid/info.svg";
|
||||
import KeyboardArrowDown from "@/../assets/icon-12px-solid/keyboard-arrow-down.svg";
|
||||
import KeyboardArrowLeft from "@/../assets/icon-12px-solid/keyboard-arrow-left.svg";
|
||||
import KeyboardArrowRight from "@/../assets/icon-12px-solid/keyboard-arrow-right.svg";
|
||||
import KeyboardArrowUp from "@/../assets/icon-12px-solid/keyboard-arrow-up.svg";
|
||||
import KeyboardBackspace from "@/../assets/icon-12px-solid/keyboard-backspace.svg";
|
||||
import KeyboardCommand from "@/../assets/icon-12px-solid/keyboard-command.svg";
|
||||
import KeyboardControl from "@/../assets/icon-12px-solid/keyboard-control.svg";
|
||||
import KeyboardEnter from "@/../assets/icon-12px-solid/keyboard-enter.svg";
|
||||
import KeyboardOption from "@/../assets/icon-12px-solid/keyboard-option.svg";
|
||||
import KeyboardShift from "@/../assets/icon-12px-solid/keyboard-shift.svg";
|
||||
import KeyboardSpace from "@/../assets/icon-12px-solid/keyboard-space.svg";
|
||||
import KeyboardTab from "@/../assets/icon-12px-solid/keyboard-tab.svg";
|
||||
import Link from "@/../assets/icon-12px-solid/link.svg";
|
||||
import Overlays from "@/../assets/icon-12px-solid/overlays.svg";
|
||||
import Remove from "@/../assets/icon-12px-solid/remove.svg";
|
||||
import ResetColors from "@/../assets/icon-12px-solid/reset-colors.svg";
|
||||
import Snapping from "@/../assets/icon-12px-solid/snapping.svg";
|
||||
import Swap from "@/../assets/icon-12px-solid/swap.svg";
|
||||
import VerticalEllipsis from "@/../assets/icon-12px-solid/vertical-ellipsis.svg";
|
||||
import Warning from "@/../assets/icon-12px-solid/warning.svg";
|
||||
import WindowButtonWinClose from "@/../assets/icon-12px-solid/window-button-win-close.svg";
|
||||
import WindowButtonWinMaximize from "@/../assets/icon-12px-solid/window-button-win-maximize.svg";
|
||||
import WindowButtonWinMinimize from "@/../assets/icon-12px-solid/window-button-win-minimize.svg";
|
||||
import WindowButtonWinRestoreDown from "@/../assets/icon-12px-solid/window-button-win-restore-down.svg";
|
||||
|
||||
const SOLID_12PX = {
|
||||
Add: { svg: Add, size: 12 },
|
||||
Checkmark: { svg: Checkmark, size: 12 },
|
||||
CloseX: { svg: CloseX, size: 12 },
|
||||
DropdownArrow: { svg: DropdownArrow, size: 12 },
|
||||
Edit: { svg: Edit, size: 12 },
|
||||
Empty12px: { svg: Empty12px, size: 12 },
|
||||
FullscreenEnter: { svg: FullscreenEnter, size: 12 },
|
||||
FullscreenExit: { svg: FullscreenExit, size: 12 },
|
||||
Grid: { svg: Grid, size: 12 },
|
||||
Info: { svg: Info, size: 12 },
|
||||
KeyboardArrowDown: { svg: KeyboardArrowDown, size: 12 },
|
||||
KeyboardArrowLeft: { svg: KeyboardArrowLeft, size: 12 },
|
||||
KeyboardArrowRight: { svg: KeyboardArrowRight, size: 12 },
|
||||
KeyboardArrowUp: { svg: KeyboardArrowUp, size: 12 },
|
||||
KeyboardBackspace: { svg: KeyboardBackspace, size: 12 },
|
||||
KeyboardCommand: { svg: KeyboardCommand, size: 12 },
|
||||
KeyboardControl: { svg: KeyboardControl, size: 12 },
|
||||
KeyboardEnter: { svg: KeyboardEnter, size: 12 },
|
||||
KeyboardOption: { svg: KeyboardOption, size: 12 },
|
||||
KeyboardShift: { svg: KeyboardShift, size: 12 },
|
||||
KeyboardSpace: { svg: KeyboardSpace, size: 12 },
|
||||
KeyboardTab: { svg: KeyboardTab, size: 12 },
|
||||
Link: { svg: Link, size: 12 },
|
||||
Overlays: { svg: Overlays, size: 12 },
|
||||
Remove: { svg: Remove, size: 12 },
|
||||
ResetColors: { svg: ResetColors, size: 12 },
|
||||
Snapping: { svg: Snapping, size: 12 },
|
||||
Swap: { svg: Swap, size: 12 },
|
||||
VerticalEllipsis: { svg: VerticalEllipsis, size: 12 },
|
||||
Warning: { svg: Warning, size: 12 },
|
||||
WindowButtonWinClose: { svg: WindowButtonWinClose, size: 12 },
|
||||
WindowButtonWinMaximize: { svg: WindowButtonWinMaximize, size: 12 },
|
||||
WindowButtonWinMinimize: { svg: WindowButtonWinMinimize, size: 12 },
|
||||
WindowButtonWinRestoreDown: { svg: WindowButtonWinRestoreDown, size: 12 },
|
||||
} as const;
|
||||
|
||||
// 16px Solid
|
||||
import AlignBottom from "@/../assets/icon-16px-solid/align-bottom.svg";
|
||||
import AlignHorizontalCenter from "@/../assets/icon-16px-solid/align-horizontal-center.svg";
|
||||
import AlignLeft from "@/../assets/icon-16px-solid/align-left.svg";
|
||||
import AlignRight from "@/../assets/icon-16px-solid/align-right.svg";
|
||||
import AlignTop from "@/../assets/icon-16px-solid/align-top.svg";
|
||||
import AlignVerticalCenter from "@/../assets/icon-16px-solid/align-vertical-center.svg";
|
||||
import BooleanDifference from "@/../assets/icon-16px-solid/boolean-difference.svg";
|
||||
import BooleanIntersect from "@/../assets/icon-16px-solid/boolean-intersect.svg";
|
||||
import BooleanSubtractBack from "@/../assets/icon-16px-solid/boolean-subtract-back.svg";
|
||||
import BooleanSubtractFront from "@/../assets/icon-16px-solid/boolean-subtract-front.svg";
|
||||
import BooleanUnion from "@/../assets/icon-16px-solid/boolean-union.svg";
|
||||
import CheckboxChecked from "@/../assets/icon-16px-solid/checkbox-checked.svg";
|
||||
import CheckboxUnchecked from "@/../assets/icon-16px-solid/checkbox-unchecked.svg";
|
||||
import Copy from "@/../assets/icon-16px-solid/copy.svg";
|
||||
import EyeHidden from "@/../assets/icon-16px-solid/eye-hidden.svg";
|
||||
import EyeVisible from "@/../assets/icon-16px-solid/eye-visible.svg";
|
||||
import Eyedropper from "@/../assets/icon-16px-solid/eyedropper.svg";
|
||||
import File from "@/../assets/icon-16px-solid/file.svg";
|
||||
import FlipHorizontal from "@/../assets/icon-16px-solid/flip-horizontal.svg";
|
||||
import FlipVertical from "@/../assets/icon-16px-solid/flip-vertical.svg";
|
||||
import Folder from "@/../assets/icon-16px-solid/folder.svg";
|
||||
import GraphiteLogo from "@/../assets/icon-16px-solid/graphite-logo.svg";
|
||||
import NodeArtboard from "@/../assets/icon-16px-solid/node-artboard.svg";
|
||||
import NodeBlur from "@/../assets/icon-16px-solid/node-blur.svg";
|
||||
import NodeBrushwork from "@/../assets/icon-16px-solid/node-brushwork.svg";
|
||||
import NodeColorCorrection from "@/../assets/icon-16px-solid/node-color-correction.svg";
|
||||
import NodeFolder from "@/../assets/icon-16px-solid/node-folder.svg";
|
||||
import NodeGradient from "@/../assets/icon-16px-solid/node-gradient.svg";
|
||||
import NodeImage from "@/../assets/icon-16px-solid/node-image.svg";
|
||||
import NodeImaginate from "@/../assets/icon-16px-solid/node-imaginate.svg";
|
||||
import NodeMagicWand from "@/../assets/icon-16px-solid/node-magic-wand.svg";
|
||||
import NodeMask from "@/../assets/icon-16px-solid/node-mask.svg";
|
||||
import NodeMotionBlur from "@/../assets/icon-16px-solid/node-motion-blur.svg";
|
||||
import NodeNodes from "@/../assets/icon-16px-solid/node-nodes.svg";
|
||||
import NodeOutput from "@/../assets/icon-16px-solid/node-output.svg";
|
||||
import NodeShape from "@/../assets/icon-16px-solid/node-shape.svg";
|
||||
import NodeText from "@/../assets/icon-16px-solid/node-text.svg";
|
||||
import NodeTransform from "@/../assets/icon-16px-solid/node-transform.svg";
|
||||
import Paste from "@/../assets/icon-16px-solid/paste.svg";
|
||||
import Random from "@/../assets/icon-16px-solid/random.svg";
|
||||
import Regenerate from "@/../assets/icon-16px-solid/regenerate.svg";
|
||||
import Reload from "@/../assets/icon-16px-solid/reload.svg";
|
||||
import Rescale from "@/../assets/icon-16px-solid/rescale.svg";
|
||||
import Reset from "@/../assets/icon-16px-solid/reset.svg";
|
||||
import Settings from "@/../assets/icon-16px-solid/settings.svg";
|
||||
import Trash from "@/../assets/icon-16px-solid/trash.svg";
|
||||
import ViewModeNormal from "@/../assets/icon-16px-solid/view-mode-normal.svg";
|
||||
import ViewModeOutline from "@/../assets/icon-16px-solid/view-mode-outline.svg";
|
||||
import ViewModePixels from "@/../assets/icon-16px-solid/view-mode-pixels.svg";
|
||||
import ViewportDesignMode from "@/../assets/icon-16px-solid/viewport-design-mode.svg";
|
||||
import ViewportGuideMode from "@/../assets/icon-16px-solid/viewport-guide-mode.svg";
|
||||
import ViewportSelectMode from "@/../assets/icon-16px-solid/viewport-select-mode.svg";
|
||||
import ZoomIn from "@/../assets/icon-16px-solid/zoom-in.svg";
|
||||
import ZoomOut from "@/../assets/icon-16px-solid/zoom-out.svg";
|
||||
import ZoomReset from "@/../assets/icon-16px-solid/zoom-reset.svg";
|
||||
|
||||
const SOLID_16PX = {
|
||||
AlignBottom: { svg: AlignBottom, size: 16 },
|
||||
AlignHorizontalCenter: { svg: AlignHorizontalCenter, size: 16 },
|
||||
AlignLeft: { svg: AlignLeft, size: 16 },
|
||||
AlignRight: { svg: AlignRight, size: 16 },
|
||||
AlignTop: { svg: AlignTop, size: 16 },
|
||||
AlignVerticalCenter: { svg: AlignVerticalCenter, size: 16 },
|
||||
BooleanDifference: { svg: BooleanDifference, size: 16 },
|
||||
BooleanIntersect: { svg: BooleanIntersect, size: 16 },
|
||||
BooleanSubtractBack: { svg: BooleanSubtractBack, size: 16 },
|
||||
BooleanSubtractFront: { svg: BooleanSubtractFront, size: 16 },
|
||||
BooleanUnion: { svg: BooleanUnion, size: 16 },
|
||||
CheckboxChecked: { svg: CheckboxChecked, size: 16 },
|
||||
CheckboxUnchecked: { svg: CheckboxUnchecked, size: 16 },
|
||||
Copy: { svg: Copy, size: 16 },
|
||||
Eyedropper: { svg: Eyedropper, size: 16 },
|
||||
EyeHidden: { svg: EyeHidden, size: 16 },
|
||||
EyeVisible: { svg: EyeVisible, size: 16 },
|
||||
File: { svg: File, size: 16 },
|
||||
FlipHorizontal: { svg: FlipHorizontal, size: 16 },
|
||||
FlipVertical: { svg: FlipVertical, size: 16 },
|
||||
Folder: { svg: Folder, size: 16 },
|
||||
GraphiteLogo: { svg: GraphiteLogo, size: 16 },
|
||||
NodeArtboard: { svg: NodeArtboard, size: 16 },
|
||||
NodeBlur: { svg: NodeBlur, size: 16 },
|
||||
NodeBrushwork: { svg: NodeBrushwork, size: 16 },
|
||||
NodeColorCorrection: { svg: NodeColorCorrection, size: 16 },
|
||||
NodeFolder: { svg: NodeFolder, size: 16 },
|
||||
NodeGradient: { svg: NodeGradient, size: 16 },
|
||||
NodeImage: { svg: NodeImage, size: 16 },
|
||||
NodeImaginate: { svg: NodeImaginate, size: 16 },
|
||||
NodeMagicWand: { svg: NodeMagicWand, size: 16 },
|
||||
NodeMask: { svg: NodeMask, size: 16 },
|
||||
NodeMotionBlur: { svg: NodeMotionBlur, size: 16 },
|
||||
NodeNodes: { svg: NodeNodes, size: 16 },
|
||||
NodeOutput: { svg: NodeOutput, size: 16 },
|
||||
NodeShape: { svg: NodeShape, size: 16 },
|
||||
NodeText: { svg: NodeText, size: 16 },
|
||||
NodeTransform: { svg: NodeTransform, size: 16 },
|
||||
Paste: { svg: Paste, size: 16 },
|
||||
Random: { svg: Random, size: 16 },
|
||||
Regenerate: { svg: Regenerate, size: 16 },
|
||||
Reload: { svg: Reload, size: 16 },
|
||||
Rescale: { svg: Rescale, size: 16 },
|
||||
Reset: { svg: Reset, size: 16 },
|
||||
Settings: { svg: Settings, size: 16 },
|
||||
Trash: { svg: Trash, size: 16 },
|
||||
ViewModeNormal: { svg: ViewModeNormal, size: 16 },
|
||||
ViewModeOutline: { svg: ViewModeOutline, size: 16 },
|
||||
ViewModePixels: { svg: ViewModePixels, size: 16 },
|
||||
ViewportDesignMode: { svg: ViewportDesignMode, size: 16 },
|
||||
ViewportGuideMode: { svg: ViewportGuideMode, size: 16 },
|
||||
ViewportSelectMode: { svg: ViewportSelectMode, size: 16 },
|
||||
ZoomIn: { svg: ZoomIn, size: 16 },
|
||||
ZoomOut: { svg: ZoomOut, size: 16 },
|
||||
ZoomReset: { svg: ZoomReset, size: 16 },
|
||||
} as const;
|
||||
|
||||
// 16px Two-Tone
|
||||
import MouseHintDrag from "@/../assets/icon-16px-two-tone/mouse-hint-drag.svg";
|
||||
import MouseHintLmbDrag from "@/../assets/icon-16px-two-tone/mouse-hint-lmb-drag.svg";
|
||||
import MouseHintLmb from "@/../assets/icon-16px-two-tone/mouse-hint-lmb.svg";
|
||||
import MouseHintMmbDrag from "@/../assets/icon-16px-two-tone/mouse-hint-mmb-drag.svg";
|
||||
import MouseHintMmb from "@/../assets/icon-16px-two-tone/mouse-hint-mmb.svg";
|
||||
import MouseHintNone from "@/../assets/icon-16px-two-tone/mouse-hint-none.svg";
|
||||
import MouseHintRmbDrag from "@/../assets/icon-16px-two-tone/mouse-hint-rmb-drag.svg";
|
||||
import MouseHintRmb from "@/../assets/icon-16px-two-tone/mouse-hint-rmb.svg";
|
||||
import MouseHintScrollDown from "@/../assets/icon-16px-two-tone/mouse-hint-scroll-down.svg";
|
||||
import MouseHintScrollUp from "@/../assets/icon-16px-two-tone/mouse-hint-scroll-up.svg";
|
||||
|
||||
const TWO_TONE_16PX = {
|
||||
MouseHintDrag: { svg: MouseHintDrag, size: 16 },
|
||||
MouseHintLmb: { svg: MouseHintLmb, size: 16 },
|
||||
MouseHintLmbDrag: { svg: MouseHintLmbDrag, size: 16 },
|
||||
MouseHintMmb: { svg: MouseHintMmb, size: 16 },
|
||||
MouseHintMmbDrag: { svg: MouseHintMmbDrag, size: 16 },
|
||||
MouseHintNone: { svg: MouseHintNone, size: 16 },
|
||||
MouseHintRmb: { svg: MouseHintRmb, size: 16 },
|
||||
MouseHintRmbDrag: { svg: MouseHintRmbDrag, size: 16 },
|
||||
MouseHintScrollDown: { svg: MouseHintScrollDown, size: 16 },
|
||||
MouseHintScrollUp: { svg: MouseHintScrollUp, size: 16 },
|
||||
} as const;
|
||||
|
||||
// 24px Two-Tone
|
||||
import GeneralArtboardTool from "@/../assets/icon-24px-two-tone/general-artboard-tool.svg";
|
||||
import GeneralEyedropperTool from "@/../assets/icon-24px-two-tone/general-eyedropper-tool.svg";
|
||||
import GeneralFillTool from "@/../assets/icon-24px-two-tone/general-fill-tool.svg";
|
||||
import GeneralGradientTool from "@/../assets/icon-24px-two-tone/general-gradient-tool.svg";
|
||||
import GeneralNavigateTool from "@/../assets/icon-24px-two-tone/general-navigate-tool.svg";
|
||||
import GeneralSelectTool from "@/../assets/icon-24px-two-tone/general-select-tool.svg";
|
||||
import RasterBrushTool from "@/../assets/icon-24px-two-tone/raster-brush-tool.svg";
|
||||
import RasterCloneTool from "@/../assets/icon-24px-two-tone/raster-clone-tool.svg";
|
||||
import RasterDetailTool from "@/../assets/icon-24px-two-tone/raster-detail-tool.svg";
|
||||
import RasterHealTool from "@/../assets/icon-24px-two-tone/raster-heal-tool.svg";
|
||||
import RasterImaginateTool from "@/../assets/icon-24px-two-tone/raster-imaginate-tool.svg";
|
||||
import RasterNodesTool from "@/../assets/icon-24px-two-tone/raster-nodes-tool.svg";
|
||||
import RasterPatchTool from "@/../assets/icon-24px-two-tone/raster-patch-tool.svg";
|
||||
import RasterRelightTool from "@/../assets/icon-24px-two-tone/raster-relight-tool.svg";
|
||||
import VectorEllipseTool from "@/../assets/icon-24px-two-tone/vector-ellipse-tool.svg";
|
||||
import VectorFreehandTool from "@/../assets/icon-24px-two-tone/vector-freehand-tool.svg";
|
||||
import VectorLineTool from "@/../assets/icon-24px-two-tone/vector-line-tool.svg";
|
||||
import VectorPathTool from "@/../assets/icon-24px-two-tone/vector-path-tool.svg";
|
||||
import VectorPenTool from "@/../assets/icon-24px-two-tone/vector-pen-tool.svg";
|
||||
import VectorRectangleTool from "@/../assets/icon-24px-two-tone/vector-rectangle-tool.svg";
|
||||
import VectorShapeTool from "@/../assets/icon-24px-two-tone/vector-shape-tool.svg";
|
||||
import VectorSplineTool from "@/../assets/icon-24px-two-tone/vector-spline-tool.svg";
|
||||
import VectorTextTool from "@/../assets/icon-24px-two-tone/vector-text-tool.svg";
|
||||
|
||||
const TWO_TONE_24PX = {
|
||||
GeneralArtboardTool: { svg: GeneralArtboardTool, size: 24 },
|
||||
GeneralEyedropperTool: { svg: GeneralEyedropperTool, size: 24 },
|
||||
GeneralFillTool: { svg: GeneralFillTool, size: 24 },
|
||||
GeneralGradientTool: { svg: GeneralGradientTool, size: 24 },
|
||||
GeneralNavigateTool: { svg: GeneralNavigateTool, size: 24 },
|
||||
GeneralSelectTool: { svg: GeneralSelectTool, size: 24 },
|
||||
RasterImaginateTool: { svg: RasterImaginateTool, size: 24 },
|
||||
RasterNodesTool: { svg: RasterNodesTool, size: 24 },
|
||||
RasterBrushTool: { svg: RasterBrushTool, size: 24 },
|
||||
RasterCloneTool: { svg: RasterCloneTool, size: 24 },
|
||||
RasterDetailTool: { svg: RasterDetailTool, size: 24 },
|
||||
RasterHealTool: { svg: RasterHealTool, size: 24 },
|
||||
RasterPatchTool: { svg: RasterPatchTool, size: 24 },
|
||||
RasterRelightTool: { svg: RasterRelightTool, size: 24 },
|
||||
VectorEllipseTool: { svg: VectorEllipseTool, size: 24 },
|
||||
VectorFreehandTool: { svg: VectorFreehandTool, size: 24 },
|
||||
VectorLineTool: { svg: VectorLineTool, size: 24 },
|
||||
VectorPathTool: { svg: VectorPathTool, size: 24 },
|
||||
VectorPenTool: { svg: VectorPenTool, size: 24 },
|
||||
VectorRectangleTool: { svg: VectorRectangleTool, size: 24 },
|
||||
VectorShapeTool: { svg: VectorShapeTool, size: 24 },
|
||||
VectorSplineTool: { svg: VectorSplineTool, size: 24 },
|
||||
VectorTextTool: { svg: VectorTextTool, size: 24 },
|
||||
} as const;
|
||||
|
||||
// All icons
|
||||
const ICON_LIST = {
|
||||
...GRAPHICS,
|
||||
...SOLID_12PX,
|
||||
...SOLID_16PX,
|
||||
...TWO_TONE_16PX,
|
||||
...TWO_TONE_24PX,
|
||||
} as const;
|
||||
|
||||
// Exported icons and types
|
||||
export const ICONS: IconDefinitionType<typeof ICON_LIST> = ICON_LIST;
|
||||
export const ICON_SVG_STRINGS = Object.fromEntries(Object.entries(ICONS).map(([name, data]) => [name, data.svg]));
|
||||
|
||||
export type IconName = keyof typeof ICONS;
|
||||
export type IconSize = undefined | 12 | 16 | 24 | 32;
|
||||
|
||||
// The following helper type declarations allow us to avoid manually maintaining the `IconName` type declaration as a string union paralleling the keys of the
|
||||
// icon definitions. It lets TypeScript do that for us. Our goal is to define the big key-value pair of icons by constraining its values, but inferring its keys.
|
||||
// Constraining its values means that TypeScript can make sure each icon definition has a valid size number from the union of numbers that is `IconSize`.
|
||||
// Inferring its keys means we don't have to specify a supertype like `string` or `any` for the key-value pair's keys, which would prevent us from accessing
|
||||
// the individual keys with `keyof typeof`. Absent a specified type for the keys, TypeScript falls back to inferring that the key-value pair's type is the
|
||||
// map of all its individual entries. Having the full list of entries lets us automatically set the `IconName` type to the union of strings that is the full
|
||||
// list of keys. The result is that we don't have to maintain a separate list of icon names since this scheme infers it from the keys of the icon definitions.
|
||||
// Based on https://stackoverflow.com/a/64119715/775283
|
||||
type IconDefinition = { svg: string; size: IconSize };
|
||||
type EvaluateType<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
||||
type IconDefinitionType<T extends Record<string, IconDefinition>> = EvaluateType<{ [key in keyof T]: IconDefinition }>;
|
||||
Reference in New Issue
Block a user