From 2a30d860077ab6bcfc822c650e36e6255170b967 Mon Sep 17 00:00:00 2001 From: Owais Jamil Date: Fri, 17 Jul 2026 23:31:22 -0500 Subject: [PATCH] refactor: migrate more UI to ui package --- ROADMAP.md | 13 +- .../src/lib/components/HistoryViewer.svelte | 2 +- apps/web/src/lib/components/Icon.svelte | 63 ------- .../src/lib/components/StencilPalette.svelte | 3 +- apps/web/src/lib/components/Toolbar.svelte | 88 +++++++--- .../src/lib/filebrowser/FileBrowser.svelte | 4 +- .../src/lib/tests/BrushPopover.svelte.test.ts | 162 ------------------ .../tests/components/Dialog.svelte.test.ts | 96 ----------- .../lib/tests/components/Sheet.svelte.test.ts | 131 -------------- apps/web/src/lib/theme.svelte.ts | 76 ++++---- packages/ui/README.md | 5 + .../lib/components/BrushPopover.stories.ts | 26 +++ .../src/lib/components/BrushPopover.svelte | 61 ++++--- .../components/BrushPopover.svelte.test.ts | 52 ++++++ .../ui/src/lib/components/Dialog.stories.ts | 18 ++ .../ui}/src/lib/components/Dialog.svelte | 39 +++-- .../src/lib/components/Dialog.svelte.test.ts | 49 ++++++ .../ui/src/lib/components/DialogStory.svelte | 47 +++++ .../ui/src/lib/components/Icon.stories.ts | 18 ++ packages/ui/src/lib/components/Icon.svelte | 9 +- .../ui/src/lib/components/Sheet.stories.ts | 19 ++ .../ui}/src/lib/components/Sheet.svelte | 31 ++-- .../src/lib/components/Sheet.svelte.test.ts | 37 ++++ .../ui/src/lib/components/SheetStory.svelte | 42 +++++ packages/ui/src/lib/icons.ts | 35 ++-- packages/ui/src/lib/index.ts | 30 ++-- packages/ui/src/lib/styles/icons.css | 5 + packages/ui/vitest.setup.ts | 4 + 28 files changed, 552 insertions(+), 613 deletions(-) delete mode 100644 apps/web/src/lib/components/Icon.svelte delete mode 100644 apps/web/src/lib/tests/BrushPopover.svelte.test.ts delete mode 100644 apps/web/src/lib/tests/components/Dialog.svelte.test.ts delete mode 100644 apps/web/src/lib/tests/components/Sheet.svelte.test.ts create mode 100644 packages/ui/src/lib/components/BrushPopover.stories.ts rename {apps/web => packages/ui}/src/lib/components/BrushPopover.svelte (86%) create mode 100644 packages/ui/src/lib/components/BrushPopover.svelte.test.ts create mode 100644 packages/ui/src/lib/components/Dialog.stories.ts rename {apps/web => packages/ui}/src/lib/components/Dialog.svelte (72%) create mode 100644 packages/ui/src/lib/components/Dialog.svelte.test.ts create mode 100644 packages/ui/src/lib/components/DialogStory.svelte create mode 100644 packages/ui/src/lib/components/Icon.stories.ts create mode 100644 packages/ui/src/lib/components/Sheet.stories.ts rename {apps/web => packages/ui}/src/lib/components/Sheet.svelte (84%) create mode 100644 packages/ui/src/lib/components/Sheet.svelte.test.ts create mode 100644 packages/ui/src/lib/components/SheetStory.svelte diff --git a/ROADMAP.md b/ROADMAP.md index e04267f..f6dfb57 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -37,8 +37,9 @@ the CLI and a bundled `SKILL.md`; MCP and UI automation are not part of vNext. - The pnpm monorepo contains a TypeScript core, Canvas 2D renderer, SvelteKit web UI, and Tauri 2 wrapper. - `@inkfinite/ui` provides shared Svelte components, theme tokens, fonts, and - icons for the browser and the Tauri-hosted frontend. `apps/web` imports the - shared stylesheet once and uses shared controls in its desktop vertical slice. + icons for the browser and the Tauri-hosted frontend. Shared buttons, icons, + panels, toolbars, dialogs, sheets, and brush controls have package-owned tests + and Storybook stories. `apps/web` keeps document-aware panels and adapters. - TypeScript currently owns a flat page/shape model, snapshot undo/redo, tools, and browser persistence. Web documents use Dexie; desktop documents use a thin adapter over Rust-owned sessions and typed Tauri commands. @@ -191,7 +192,10 @@ that boundary into one history command, and the desktop session adapter builds one Rust transaction before replacing its mirror from the returned snapshot. `@inkfinite/input-dom` owns browser listener and coordinate normalization. A browser integration test covers drag, simulated Rust commit, patch-driven -redraw, and undo back to the original document. +redraw, and undo back to the original document. The final UI boundary moved the +dependency-free dialog, sheet, brush popover, and remaining semantic icons into +`@inkfinite/ui`, along with their tests and Storybook stories. Document-aware +panels remain in `apps/web` and compose those shared controls. One Inkfinite transaction maps to one Automerge change. Causal heads, rather than a scalar revision, are the concurrency token. A local sequence number may @@ -455,8 +459,7 @@ recovery prompts, and release migrations. - Adapt the standalone browser runtime and Dexie persistence to the v2 Rust/CRDT authority after the desktop contracts and file format stabilize. Its migration must backfill every existing board with a default layer and preserve shape - order. Shared `apps/web` components and `@inkfinite/ui` adoption remain part of - milestone 3; keep the browser build green while desktop behavior changes. + order. Keep the shared browser build green while desktop behavior changes. - Add hosted sync relay, identity, invitations, permissions, and ephemeral presence after local peer sync is correct and threat-modeled. - Consider WebGL, OffscreenCanvas, third-party shape plugins, Figma import, diff --git a/apps/web/src/lib/components/HistoryViewer.svelte b/apps/web/src/lib/components/HistoryViewer.svelte index ec04c49..7e060fe 100644 --- a/apps/web/src/lib/components/HistoryViewer.svelte +++ b/apps/web/src/lib/components/HistoryViewer.svelte @@ -7,7 +7,7 @@ */ import type { Store } from '@inkfinite/core'; - import Sheet from './Sheet.svelte'; + import { Sheet } from '@inkfinite/ui'; type Props = { store: Store; open: boolean; onClose: () => void }; diff --git a/apps/web/src/lib/components/Icon.svelte b/apps/web/src/lib/components/Icon.svelte deleted file mode 100644 index 5ed5577..0000000 --- a/apps/web/src/lib/components/Icon.svelte +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - diff --git a/apps/web/src/lib/components/StencilPalette.svelte b/apps/web/src/lib/components/StencilPalette.svelte index 9dc57e4..ec15285 100644 --- a/apps/web/src/lib/components/StencilPalette.svelte +++ b/apps/web/src/lib/components/StencilPalette.svelte @@ -2,9 +2,8 @@ import { onMount } from 'svelte'; import { SvelteSet } from 'svelte/reactivity'; import { stencils } from '@inkfinite/core'; + import { Icon, Sheet } from '@inkfinite/ui'; import { startDrag, endDrag, draggingStencil } from '../dnd.svelte'; - import Sheet from '$lib/components/Sheet.svelte'; - import Icon from '$lib/components/Icon.svelte'; type Stencil = stencils.Stencil; const { registry, registerBuiltinStencils } = stencils; diff --git a/apps/web/src/lib/components/Toolbar.svelte b/apps/web/src/lib/components/Toolbar.svelte index 7fead8d..1445cf5 100644 --- a/apps/web/src/lib/components/Toolbar.svelte +++ b/apps/web/src/lib/components/Toolbar.svelte @@ -1,5 +1,5 @@ - let { brush, onBrushChange, disabled = false }: Props = $props(); + + + + +
+

Shared surface

+

About this board

+

+ Dialog content stays in the consuming app while focus and dismissal remain consistent. +

+ +
+
+ + diff --git a/packages/ui/src/lib/components/Icon.stories.ts b/packages/ui/src/lib/components/Icon.stories.ts new file mode 100644 index 0000000..ea7bd01 --- /dev/null +++ b/packages/ui/src/lib/components/Icon.stories.ts @@ -0,0 +1,18 @@ +import type { Meta, StoryObj } from '@storybook/sveltekit'; + +import Icon from './Icon.svelte'; +import { ICONS } from '../icons'; + +const meta = { + title: 'Controls/Icon', + component: Icon, + tags: ['autodocs'], + args: { name: 'draw', size: 24 }, + argTypes: { name: { control: 'select', options: Object.keys(ICONS) } } +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; +export const Labeled: Story = { args: { label: 'Draw', name: 'draw' } }; diff --git a/packages/ui/src/lib/components/Icon.svelte b/packages/ui/src/lib/components/Icon.svelte index c91caad..24a900d 100644 --- a/packages/ui/src/lib/components/Icon.svelte +++ b/packages/ui/src/lib/components/Icon.svelte @@ -5,16 +5,18 @@ /** Props for the shared Iconify-backed icon primitive. */ export interface IconProps extends Omit, 'children'> { + color?: string; label?: string; name: IconName; - size?: string; + size?: number | string; } + style:--ink-icon-size={resolvedSize} + style:color> diff --git a/packages/ui/src/lib/icons.ts b/packages/ui/src/lib/icons.ts index 0de36a0..2d43295 100644 --- a/packages/ui/src/lib/icons.ts +++ b/packages/ui/src/lib/icons.ts @@ -1,18 +1,27 @@ /** Iconify classes used by Inkfinite's shared icon component. */ export const ICONS = { - add: "i-ph-plus-bold", - arrow: "i-tabler-arrow-up-right", - check: "i-bi-check-lg", - close: "i-ph-x-bold", - dark: "i-tabler-moon", - delete: "i-bi-trash3", - draw: "i-ph-pencil-simple-line-bold", - light: "i-tabler-sun", - menu: "i-bi-list", - redo: "i-tabler-arrow-forward-up", - save: "i-ph-floppy-disk-back-bold", - settings: "i-bi-sliders", - undo: "i-tabler-arrow-back-up", + add: 'i-ph-plus-bold', + arrow: 'i-tabler-arrow-up-right', + check: 'i-bi-check-lg', + close: 'i-ph-x-bold', + dark: 'i-tabler-moon', + delete: 'i-bi-trash3', + draw: 'i-ph-pencil-simple-line-bold', + folder: 'i-ph-folder-bold', + 'grid-dots': 'i-tabler-grid-dots', + 'grip-vertical': 'i-tabler-grip-vertical', + 'info-circle': 'i-tabler-info-circle', + light: 'i-tabler-sun', + menu: 'i-bi-list', + moon: 'i-tabler-moon', + pencil: 'i-ph-pencil-simple-line-bold', + redo: 'i-tabler-arrow-forward-up', + save: 'i-ph-floppy-disk-back-bold', + search: 'i-ph-magnifying-glass-bold', + settings: 'i-bi-sliders', + sun: 'i-tabler-sun', + trash: 'i-bi-trash3', + undo: 'i-tabler-arrow-back-up' } as const; /** A semantic icon name supported by the shared icon component. */ diff --git a/packages/ui/src/lib/index.ts b/packages/ui/src/lib/index.ts index 79d19c8..c2f15db 100644 --- a/packages/ui/src/lib/index.ts +++ b/packages/ui/src/lib/index.ts @@ -1,14 +1,16 @@ -export { default as Button } from "./components/Button.svelte"; -export type { ButtonProps, ButtonVariant } from "./components/Button.svelte"; -export { default as Icon } from "./components/Icon.svelte"; -export type { IconProps } from "./components/Icon.svelte"; -export { default as IconButton } from "./components/IconButton.svelte"; -export type { IconButtonProps } from "./components/IconButton.svelte"; -export { default as Panel } from "./components/Panel.svelte"; -export type { PanelProps } from "./components/Panel.svelte"; -export { default as Toolbar } from "./components/Toolbar.svelte"; -export type { ToolbarProps } from "./components/Toolbar.svelte"; -export { ICONS } from "./icons"; -export type { IconName } from "./icons"; -export { applyInkTheme } from "./theme"; -export type { InkTheme } from "./theme"; +export { default as Button } from './components/Button.svelte'; +export type { ButtonProps, ButtonVariant } from './components/Button.svelte'; + +export { default as BrushPopover } from './components/BrushPopover.svelte'; +export type { BrushPopoverProps, BrushSettings } from './components/BrushPopover.svelte'; + +export { default as Sheet } from './components/Sheet.svelte'; +export type { SheetProps, SheetSide } from './components/Sheet.svelte'; + +export { default as Dialog, type DialogProps } from './components/Dialog.svelte'; +export { default as Icon, type IconProps } from './components/Icon.svelte'; +export { default as IconButton, type IconButtonProps } from './components/IconButton.svelte'; +export { default as Panel, type PanelProps } from './components/Panel.svelte'; +export { default as Toolbar, type ToolbarProps } from './components/Toolbar.svelte'; +export { ICONS, type IconName } from './icons'; +export { applyInkTheme, type InkTheme } from './theme'; diff --git a/packages/ui/src/lib/styles/icons.css b/packages/ui/src/lib/styles/icons.css index 20f76af..5b454b6 100644 --- a/packages/ui/src/lib/styles/icons.css +++ b/packages/ui/src/lib/styles/icons.css @@ -5,11 +5,16 @@ .i-bi-sliders{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 16 16' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' fill-rule='evenodd' d='M11.5 2a1.5 1.5 0 1 0 0 3a1.5 1.5 0 0 0 0-3M9.05 3a2.5 2.5 0 0 1 4.9 0H16v1h-2.05a2.5 2.5 0 0 1-4.9 0H0V3zM4.5 7a1.5 1.5 0 1 0 0 3a1.5 1.5 0 0 0 0-3M2.05 8a2.5 2.5 0 0 1 4.9 0H16v1H6.95a2.5 2.5 0 0 1-4.9 0H0V8zm9.45 4a1.5 1.5 0 1 0 0 3a1.5 1.5 0 0 0 0-3m-2.45 1a2.5 2.5 0 0 1 4.9 0H16v1h-2.05a2.5 2.5 0 0 1-4.9 0H0v-1z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} .i-bi-trash3{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 16 16' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M6.5 1h3a.5.5 0 0 1 .5.5v1H6v-1a.5.5 0 0 1 .5-.5M11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3A1.5 1.5 0 0 0 5 1.5v1H1.5a.5.5 0 0 0 0 1h.538l.853 10.66A2 2 0 0 0 4.885 16h6.23a2 2 0 0 0 1.994-1.84l.853-10.66h.538a.5.5 0 0 0 0-1zm1.958 1l-.846 10.58a1 1 0 0 1-.997.92h-6.23a1 1 0 0 1-.997-.92L3.042 3.5zm-7.487 1a.5.5 0 0 1 .528.47l.5 8.5a.5.5 0 0 1-.998.06L5 5.03a.5.5 0 0 1 .47-.53Zm5.058 0a.5.5 0 0 1 .47.53l-.5 8.5a.5.5 0 1 1-.998-.06l.5-8.5a.5.5 0 0 1 .528-.47M8 4.5a.5.5 0 0 1 .5.5v8.5a.5.5 0 0 1-1 0V5a.5.5 0 0 1 .5-.5'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} .i-ph-floppy-disk-back-bold{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 256 256' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M208 28H83.31a19.86 19.86 0 0 0-14.14 5.86L33.86 69.17A19.86 19.86 0 0 0 28 83.31V208a20 20 0 0 0 20 20h160a20 20 0 0 0 20-20V48a20 20 0 0 0-20-20M92 52h72v20H92Zm112 152H52V85l16-16v7a20 20 0 0 0 20 20h80a20 20 0 0 0 20-20V52h16Zm-76-96a42 42 0 1 0 42 42a42 42 0 0 0-42-42m0 60a18 18 0 1 1 18-18a18 18 0 0 1-18 18'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} +.i-ph-folder-bold{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 256 256' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M216 68h-82.61l-26-29.29a20 20 0 0 0-15-6.71H40a20 20 0 0 0-20 20v148.62A19.41 19.41 0 0 0 39.38 220h177.51A19.13 19.13 0 0 0 236 200.89V88a20 20 0 0 0-20-20M44 56h46.61l10.67 12H44Zm168 140H44V92h168Z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} +.i-ph-magnifying-glass-bold{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 256 256' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M232.49 215.51L185 168a92.12 92.12 0 1 0-17 17l47.53 47.54a12 12 0 0 0 17-17ZM44 112a68 68 0 1 1 68 68a68.07 68.07 0 0 1-68-68'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} .i-ph-pencil-simple-line-bold{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 256 256' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='m230.15 70.54l-44.69-44.68a20 20 0 0 0-28.28 0L33.86 149.17A19.86 19.86 0 0 0 28 163.31V208a20 20 0 0 0 20 20h168a12 12 0 0 0 0-24h-91L230.15 98.83a20 20 0 0 0 0-28.29M91 204H52v-39l84-84l39 39Zm101-101l-39-39l18.34-18.34l39 39Z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} .i-ph-plus-bold{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 256 256' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M228 128a12 12 0 0 1-12 12h-76v76a12 12 0 0 1-24 0v-76H40a12 12 0 0 1 0-24h76V40a12 12 0 0 1 24 0v76h76a12 12 0 0 1 12 12'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} .i-ph-x-bold{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 256 256' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='currentColor' d='M208.49 191.51a12 12 0 0 1-17 17L128 145l-63.51 63.49a12 12 0 0 1-17-17L111 128L47.51 64.49a12 12 0 0 1 17-17L128 111l63.51-63.52a12 12 0 0 1 17 17L145 128Z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} .i-tabler-arrow-back-up{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cg fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m9 14l-4-4l4-4'/%3E%3Cpath d='M5 10h11a4 4 0 1 1 0 8h-1'/%3E%3C/g%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} .i-tabler-arrow-forward-up{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cg fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m15 14l4-4l-4-4'/%3E%3Cpath d='M19 10H8a4 4 0 1 0 0 8h1'/%3E%3C/g%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} .i-tabler-arrow-up-right{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M17 7L7 17M8 7h9v9'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} +.i-tabler-grid-dots{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 5a1 1 0 1 0 2 0a1 1 0 1 0-2 0m7 0a1 1 0 1 0 2 0a1 1 0 1 0-2 0m7 0a1 1 0 1 0 2 0a1 1 0 1 0-2 0M4 12a1 1 0 1 0 2 0a1 1 0 1 0-2 0m7 0a1 1 0 1 0 2 0a1 1 0 1 0-2 0m7 0a1 1 0 1 0 2 0a1 1 0 1 0-2 0M4 19a1 1 0 1 0 2 0a1 1 0 1 0-2 0m7 0a1 1 0 1 0 2 0a1 1 0 1 0-2 0m7 0a1 1 0 1 0 2 0a1 1 0 1 0-2 0'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} +.i-tabler-grip-vertical{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M8 5a1 1 0 1 0 2 0a1 1 0 1 0-2 0m0 7a1 1 0 1 0 2 0a1 1 0 1 0-2 0m0 7a1 1 0 1 0 2 0a1 1 0 1 0-2 0m6-14a1 1 0 1 0 2 0a1 1 0 1 0-2 0m0 7a1 1 0 1 0 2 0a1 1 0 1 0-2 0m0 7a1 1 0 1 0 2 0a1 1 0 1 0-2 0'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} +.i-tabler-info-circle{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cg fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M3 12a9 9 0 1 0 18 0a9 9 0 0 0-18 0m9-3h.01'/%3E%3Cpath d='M11 12h1v4h1'/%3E%3C/g%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} .i-tabler-moon{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M12 3h.393a7.5 7.5 0 0 0 7.92 12.446A9 9 0 1 1 12 2.992z'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} .i-tabler-sun{--un-icon:url("data:image/svg+xml;utf8,%3Csvg viewBox='0 0 24 24' display='inline-block' flex-shrink='0' vertical-align='-0.125em' width='1em' height='1em' xmlns='http://www.w3.org/2000/svg' %3E%3Cpath fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M8 12a4 4 0 1 0 8 0a4 4 0 1 0-8 0m-5 0h1m8-9v1m8 8h1m-9 8v1M5.6 5.6l.7.7m12.1-.7l-.7.7m0 11.4l.7.7m-12.1-.7l-.7.7'/%3E%3C/svg%3E");-webkit-mask:var(--un-icon) no-repeat;mask:var(--un-icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit;display:inline-block;flex-shrink:0;vertical-align:-0.125em;width:1em;height:1em;} diff --git a/packages/ui/vitest.setup.ts b/packages/ui/vitest.setup.ts index f149f27..f91c8d3 100644 --- a/packages/ui/vitest.setup.ts +++ b/packages/ui/vitest.setup.ts @@ -1 +1,5 @@ import "@testing-library/jest-dom/vitest"; +import { cleanup } from "@testing-library/svelte"; +import { afterEach } from "vitest"; + +afterEach(cleanup); -- 2.51.2