@heyramzi/ui 2.0.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +48 -24
- package/scripts/sync-shadcn.mjs +3 -4
- package/src/agents/agent-avatar.svelte +604 -575
- package/src/agents/agent-cast.svelte +179 -183
- package/src/agents/demo.svelte +125 -113
- package/src/agents/helpers.ts +23 -17
- package/src/agents/index.ts +4 -4
- package/src/agents/page-state.ts +6 -6
- package/src/agents/types.ts +6 -6
- package/src/ai/ai-button/AiButton.svelte +4 -12
- package/src/ai/generation-progress/GenerationProgress.svelte +10 -3
- package/src/ai/prompt-input/PromptInputTextarea.svelte +1 -2
- package/src/ai/response/Response.css +2 -3
- package/src/animations/avatar-group-hover.css +2 -16
- package/src/animations/card-tilt.css +3 -6
- package/src/animations/digit-pop-in.css +2 -15
- package/src/animations/dropdown.css +4 -17
- package/src/animations/input-clear-dissolve.css +5 -18
- package/src/animations/input-shake.css +9 -41
- package/src/animations/learn-more-hover.css +17 -9
- package/src/animations/like-button.css +2 -4
- package/src/animations/page-side-by-side.css +2 -10
- package/src/animations/plus-menu-morph.css +2 -5
- package/src/animations/shimmer-text.css +5 -18
- package/src/animations/spinning-counter.css +2 -6
- package/src/animations/success-check.css +2 -15
- package/src/animations/thinking-states.css +2 -7
- package/src/brand/brand.test.ts +21 -5
- package/src/brand/index.ts +4 -10
- package/src/canvas/README.md +9 -12
- package/src/canvas/card/card-frame.svelte +43 -39
- package/src/canvas/card/resize-handles.svelte +89 -80
- package/src/canvas/chrome/chrome-zoom.svelte +101 -100
- package/src/canvas/chrome/lock-badge.svelte +8 -8
- package/src/canvas/chrome/side-handles.svelte +24 -19
- package/src/canvas/chrome/size-chip.svelte +30 -30
- package/src/canvas/chrome/snap-guides.svelte +20 -20
- package/src/canvas/components/icons/ToolIcon.svelte +8 -8
- package/src/canvas/components/shared/svg/PreviewSvg.svelte +19 -19
- package/src/canvas/components/shared/svg/ShapeOutline.svelte +71 -48
- package/src/canvas/components/shared/svg/StrokeNode.svelte +21 -27
- package/src/canvas/components/shared/svg/TextRule.svelte +25 -17
- package/src/canvas/edges/bend-handle.svelte +46 -46
- package/src/canvas/edges/edge-gradient.svelte +10 -10
- package/src/canvas/edges/gradient-edge.svelte +45 -29
- package/src/canvas/editor/lock.test.ts +6 -1
- package/src/canvas/editor/style.ts +7 -1
- package/src/canvas/headless/svg-figure.test.ts +5 -1
- package/src/canvas/lod/lod-switch.svelte +111 -106
- package/src/canvas/pen/PenField.svelte +87 -81
- package/src/canvas/pen/PenOverlay.svelte +127 -127
- package/src/canvas/pen/ShapeNode.svelte +31 -32
- package/src/canvas/pen/TextNode.svelte +54 -53
- package/src/canvas/pen/host-field.test.svelte +7 -7
- package/src/canvas/pen/shapes.ts +7 -1
- package/src/canvas/screen/GlyphIcon.svelte +22 -17
- package/src/canvas/screen/PartView.svelte +138 -72
- package/src/canvas/screen/ScreenBody.svelte +81 -60
- package/src/canvas/screen/ScreenCard.svelte +20 -20
- package/src/canvas/ui/CanvasToolbar.svelte +173 -85
- package/src/canvas/ui/FrameLayer.svelte +59 -59
- package/src/canvas/ui/PenLayer.svelte +39 -30
- package/src/canvas/ui/StylePanel.svelte +119 -102
- package/src/canvas/ui/canvas-grid.svelte +137 -129
- package/src/charts/animated-value.svelte +1 -1
- package/src/charts/area-chart.css +2 -5
- package/src/charts/area-chart.svelte +1 -1
- package/src/charts/bar-chart.css +2 -3
- package/src/charts/bar-chart.svelte +1 -1
- package/src/charts/charts.css +5 -17
- package/src/charts/crosshair.svelte +1 -1
- package/src/charts/dashboard/dashboard-empty.svelte +25 -25
- package/src/charts/dashboard/dashboard-section.svelte +24 -24
- package/src/charts/dashboard/data-panel.svelte +50 -50
- package/src/charts/dashboard/data-sort-head.svelte +56 -56
- package/src/charts/dashboard/data-table.svelte +138 -138
- package/src/charts/dashboard/panel-grid.svelte +30 -30
- package/src/charts/dashboard/period-filter.svelte +25 -25
- package/src/charts/dashboard/rating-chip.svelte +19 -19
- package/src/charts/dashboard/stat-band.svelte +32 -32
- package/src/charts/dashboard/stat-tile.svelte +106 -99
- package/src/charts/donut-chart.svelte +1 -1
- package/src/charts/edge-fade.svelte +1 -1
- package/src/charts/figure.svelte +1 -1
- package/src/charts/gauge-chart.css +4 -7
- package/src/charts/gauge-chart.svelte +1 -1
- package/src/charts/hover-focus.svelte +1 -1
- package/src/charts/legend.css +1 -3
- package/src/charts/legend.svelte +1 -1
- package/src/charts/line-chart.svelte +1 -1
- package/src/charts/number-chart.css +6 -9
- package/src/charts/number-chart.svelte +1 -1
- package/src/charts/reference-line.svelte +19 -19
- package/src/charts/reveal.svelte +1 -1
- package/src/charts/ring-chart.css +2 -4
- package/src/charts/ring-chart.svelte +1 -1
- package/src/charts/sparkline.svelte +5 -2
- package/src/charts/stat-card.svelte +1 -1
- package/src/charts/time-series-chart.css +2 -5
- package/src/charts/trend-pill.css +2 -4
- package/src/charts/trend-pill.svelte +1 -1
- package/src/components/copy/copy-button.svelte +93 -98
- package/src/components/copy/copy-button.test.ts +10 -2
- package/src/components/data-table/infinite-scroll.svelte +42 -42
- package/src/components/data-table/pagination.svelte +34 -22
- package/src/components/data-table/row-arrow.svelte +19 -16
- package/src/components/data-table/row-context-menu.svelte +52 -52
- package/src/components/data-table/sortable-head.svelte +25 -25
- package/src/components/data-table/table-skeleton.svelte +41 -36
- package/src/components/docs/doc-page.svelte +18 -9
- package/src/components/docs/on-this-page.svelte +16 -3
- package/src/components/docs/scroll-spy.svelte.ts +2 -3
- package/src/components/field-row/field-row.svelte +10 -8
- package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
- package/src/components/icon/icon.svelte +14 -14
- package/src/components/language-flag/language-flag.svelte +3 -1
- package/src/components/list-page/detail-empty.svelte +34 -34
- package/src/components/list-page/detail-header.svelte +55 -47
- package/src/components/list-page/detail-panel.svelte +51 -59
- package/src/components/list-page/detail-row.svelte +19 -19
- package/src/components/list-page/detail-stack.svelte +21 -21
- package/src/components/list-page/empty-state.svelte +30 -30
- package/src/components/list-page/filter-item.svelte +20 -20
- package/src/components/list-page/filter-popover.svelte +60 -55
- package/src/components/list-page/grouped-list.svelte +4 -2
- package/src/components/list-page/index.ts +8 -4
- package/src/components/list-page/list-page-shell.svelte +2 -5
- package/src/components/list-page/master-detail.svelte +87 -88
- package/src/components/list-page/notice-bar.svelte +38 -38
- package/src/components/list-page/prev-next.svelte +63 -63
- package/src/components/list-page/rail-body.svelte +18 -18
- package/src/components/list-page/rail-empty.svelte +23 -30
- package/src/components/list-page/rail-head.svelte +24 -24
- package/src/components/list-page/rail-row.svelte +77 -73
- package/src/components/list-page/section-host.ts +2 -3
- package/src/components/locale-switch/locale-switch.svelte +41 -41
- package/src/components/mark/mark.svelte +34 -38
- package/src/components/open-in/index.ts +1 -5
- package/src/components/open-in/open-in.svelte +40 -40
- package/src/components/picker/mark-picker.svelte +49 -49
- package/src/components/picker/picker.svelte +5 -3
- package/src/components/section-header/index.ts +1 -0
- package/src/components/section-header/section-header.svelte +1 -1
- package/src/components/section-header/section-header.test.ts +7 -1
- package/src/components/section-header/section-label.svelte +39 -0
- package/src/components/segmented/animated-tabs.svelte +31 -2
- package/src/components/segmented/collapse.test.ts +2 -1
- package/src/components/segmented/index.ts +2 -0
- package/src/components/segmented/segment.svelte +52 -49
- package/src/components/segmented/segmented-filter.svelte +79 -80
- package/src/components/segmented/segmented-nav.svelte +34 -40
- package/src/components/segmented/segmented-overflow.svelte +53 -50
- package/src/components/segmented/segmented-track.svelte +62 -46
- package/src/components/segmented/segmented.ts +2 -3
- package/src/components/star-rating-input/star-rating-input.svelte +103 -103
- package/src/components/svg/svg.svelte +4 -4
- package/src/components/table-view/table-view.svelte +17 -2
- package/src/components/table-view/table-view.test.ts +7 -1
- package/src/components/table-view/types.ts +11 -11
- package/src/components/tags-input/index.ts +13 -0
- package/src/components/tags-input/tags-input.svelte +305 -0
- package/src/components/tags-input/tags.test.ts +64 -0
- package/src/components/tags-input/tags.ts +142 -0
- package/src/components/theme/index.ts +2 -4
- package/src/components/theme/theme-provider.svelte +1 -3
- package/src/components/toolbar/index.ts +2 -0
- package/src/components/{list-page → toolbar}/toolbar-search.svelte +25 -25
- package/src/components/toolbar/toolbar.svelte +13 -9
- package/src/components/toolbar/toolbar.test.ts +10 -1
- package/src/design/index.css +21 -78
- package/src/design/polish.css +26 -35
- package/src/editor/editor-toolbar.svelte +104 -99
- package/src/editor/editor.svelte +296 -266
- package/src/editor/image-toolbar.svelte +20 -22
- package/src/editor/index.ts +1 -4
- package/src/editor/inline-editor.svelte +280 -238
- package/src/editor/markdown.ts +15 -15
- package/src/editor/renderer.svelte +71 -71
- package/src/editor/slash-menu.svelte +24 -27
- package/src/effects/animated-beam/diagrams/BeamSvg.svelte +1 -1
- package/src/effects/image-comparison/ImageComparison.svelte +11 -1
- package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +59 -46
- package/src/effects/magic-card/MagicCard.css +14 -7
- package/src/effects/marquee/Marquee.svelte +3 -5
- package/src/effects/reveal/observe.ts +0 -3
- package/src/effects/spotlight/Spotlight.svelte +1 -1
- package/src/effects/theme-toggle/ThemeToggle.css +25 -22
- package/src/effects/theme-toggle/ThemeToggle.svelte +6 -7
- package/src/gallery.test.ts +14 -4
- package/src/inbox/README.md +27 -0
- package/src/inbox/inbox.test.ts +214 -0
- package/src/inbox/index.ts +31 -0
- package/src/inbox/logic.ts +169 -0
- package/src/inbox/thread-inbox.svelte +439 -0
- package/src/inbox/types.ts +161 -0
- package/src/lib/theme-transition.ts +2 -4
- package/src/lib/tone.ts +2 -4
- package/src/lib/utils.ts +2 -2
- package/src/modules.test.ts +105 -0
- package/src/onboarding/define-tours.test.ts +55 -40
- package/src/onboarding/define-tours.ts +23 -23
- package/src/onboarding/demo.svelte +24 -5
- package/src/onboarding/index.ts +1 -8
- package/src/onboarding/onboarding-provider.svelte +19 -7
- package/src/onboarding/onboarding.svelte.ts +16 -16
- package/src/onboarding/pick.test.ts +61 -52
- package/src/onboarding/pick.ts +16 -13
- package/src/onboarding/stores.test.ts +80 -80
- package/src/onboarding/stores.ts +41 -39
- package/src/onboarding/tour-card.svelte +30 -5
- package/src/onboarding/tour-runner.svelte +12 -3
- package/src/onboarding/types.ts +20 -12
- package/src/onboarding/wait.ts +22 -22
- package/src/panel/README.md +5 -0
- package/src/panel/index.ts +2 -0
- package/src/panel/side-panel.svelte +194 -0
- package/src/record/README.md +3 -0
- package/src/record/demo-data.ts +352 -0
- package/src/record/field-section.svelte +57 -0
- package/src/record/fields.ts +194 -0
- package/src/record/format.ts +94 -0
- package/src/{tasks/record → record}/index.ts +49 -35
- package/src/{tasks/record → record}/info-list.svelte +145 -114
- package/src/record/kinds.ts +42 -0
- package/src/record/logic.ts +326 -0
- package/src/record/next-up.svelte +81 -0
- package/src/{tasks/record → record}/project-list.svelte +56 -50
- package/src/{tasks/record → record}/record-demo.svelte +130 -110
- package/src/{tasks/record → record}/record-header.svelte +37 -28
- package/src/{tasks/record → record}/record-shell.svelte +54 -54
- package/src/record/record-stats.svelte +48 -0
- package/src/record/record-timeline.svelte +251 -0
- package/src/record/record.test.ts +471 -0
- package/src/{tasks/record → record}/steps-rail.svelte +225 -216
- package/src/record/types.ts +299 -0
- package/src/record/where-we-are.svelte +125 -0
- package/src/shadcn/button/button.svelte +1 -1
- package/src/shadcn/card/card-title.svelte +1 -5
- package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
- package/src/shadcn/sheet/sheet-content.svelte +2 -4
- package/src/shadcn/table/table-cell.svelte +2 -3
- package/src/shadcn/utilities.css +3 -8
- package/src/slides/Controls.svelte +150 -124
- package/src/slides/Deck.svelte +243 -238
- package/src/slides/Fragment.svelte +64 -57
- package/src/slides/Overview.svelte +106 -101
- package/src/slides/Presenter.svelte +300 -266
- package/src/slides/Slide.svelte +185 -170
- package/src/slides/SlideList.svelte +16 -12
- package/src/slides/ambient.d.ts +1 -1
- package/src/slides/bridges.ts +42 -23
- package/src/slides/deck-controller.svelte.ts +47 -35
- package/src/slides/demo-slides.svelte +330 -306
- package/src/slides/demo.svelte +164 -160
- package/src/slides/export/capture.ts +20 -16
- package/src/slides/export/ffmpeg.ts +43 -38
- package/src/slides/export/index.ts +5 -5
- package/src/slides/export/launch.ts +3 -1
- package/src/slides/export/pdf.ts +30 -27
- package/src/slides/export/types.ts +10 -8
- package/src/slides/index.ts +11 -11
- package/src/slides/labels.ts +22 -19
- package/src/slides/layout.ts +9 -2
- package/src/slides/model.ts +4 -4
- package/src/slides/navigation.ts +43 -31
- package/src/slides/theme.css +5 -7
- package/src/slides/types.ts +9 -10
- package/src/status/README.md +18 -0
- package/src/status/define-statuses.ts +25 -0
- package/src/status/index.ts +11 -0
- package/src/{tasks → status}/status-badge.svelte +3 -1
- package/src/{tasks → status}/status-dot.svelte +1 -3
- package/src/{tasks → status}/status-icon.svelte +1 -1
- package/src/status/status-types.ts +40 -0
- package/src/tasks/README.md +1 -1
- package/src/tasks/board-order.ts +2 -4
- package/src/tasks/demo.svelte +192 -34
- package/src/tasks/detail/detail-demo.svelte +75 -15
- package/src/tasks/detail/detail-types.ts +45 -45
- package/src/tasks/detail/task-detail.svelte +40 -10
- package/src/tasks/detail/task-property.svelte +8 -2
- package/src/tasks/detail/task-thread.svelte +53 -12
- package/src/tasks/gantt/gantt-bar.svelte +17 -6
- package/src/tasks/gantt/gantt-grid.svelte +40 -9
- package/src/tasks/gantt/gantt-group-row.svelte +8 -2
- package/src/tasks/gantt/gantt-header.svelte +9 -3
- package/src/tasks/gantt/gantt-task-row.svelte +26 -6
- package/src/tasks/gantt/gantt.css +2 -1
- package/src/tasks/gantt/gantt.test.ts +4 -2
- package/src/tasks/gantt/logic.test.ts +110 -20
- package/src/tasks/gantt/logic.ts +42 -6
- package/src/tasks/inbox/inbox-card.svelte +15 -7
- package/src/tasks/inbox/inbox-draft.svelte +1 -1
- package/src/tasks/inbox/inbox-logic.ts +6 -40
- package/src/tasks/inbox/inbox-statuses.ts +24 -24
- package/src/tasks/inbox/inbox-trace.svelte +9 -3
- package/src/tasks/inbox/inbox-types.ts +54 -58
- package/src/tasks/inbox/index.ts +22 -21
- package/src/tasks/index.ts +52 -53
- package/src/tasks/kanban-board.svelte +16 -12
- package/src/tasks/kanban-types.ts +2 -3
- package/src/tasks/presets/sales.ts +7 -7
- package/src/tasks/task-gantt.svelte +28 -8
- package/src/tasks/task-list.svelte +41 -17
- package/src/tasks/time/duration.ts +40 -40
- package/src/tasks/time/time-chip.svelte +9 -2
- package/src/tasks/time/time-dot.svelte +1 -1
- package/src/tasks/time/time-ring.svelte +11 -3
- package/src/tasks/time/time-tracker.svelte +57 -15
- package/src/tasks/time/time-types.ts +57 -57
- package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
- package/src/thread/README.md +31 -0
- package/src/thread/index.ts +12 -0
- package/src/thread/logic.ts +61 -0
- package/src/thread/thread.svelte +432 -0
- package/src/thread/thread.test.ts +73 -0
- package/src/thread/types.ts +93 -0
- package/src/tokens/craft.css +17 -53
- package/src/tokens/index.css +3 -13
- package/src/tokens/palette.css +13 -11
- package/src/tokens/primitives.css +10 -23
- package/src/components/list-page/section-label.svelte +0 -39
- package/src/tasks/define-statuses.ts +0 -32
- package/src/tasks/inbox/inbox.svelte +0 -203
- package/src/tasks/record/demo-data.ts +0 -286
- package/src/tasks/record/field-section.svelte +0 -53
- package/src/tasks/record/fields.ts +0 -142
- package/src/tasks/record/format.ts +0 -87
- package/src/tasks/record/kinds.ts +0 -42
- package/src/tasks/record/logic.ts +0 -324
- package/src/tasks/record/next-up.svelte +0 -70
- package/src/tasks/record/record-stats.svelte +0 -48
- package/src/tasks/record/record-timeline.svelte +0 -231
- package/src/tasks/record/record.test.ts +0 -350
- package/src/tasks/record/types.ts +0 -280
- package/src/tasks/record/where-we-are.svelte +0 -121
- package/src/tasks/side-panel.svelte +0 -193
- package/src/tasks/status-types.ts +0 -40
- /package/src/components/{list-page → toolbar}/toolbar-trigger.ts +0 -0
- /package/src/{tasks → panel}/side-panel-types.ts +0 -0
- /package/src/{tasks/record → record}/gutter.ts +0 -0
package/src/agents/helpers.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
/* Pure helpers for the avatar: numbers, theme, lights, idle scheduling. */
|
|
2
|
-
import { DARK_INK, LIGHT_INK, luminance } from
|
|
3
|
-
import { stockLights } from
|
|
2
|
+
import { DARK_INK, LIGHT_INK, luminance } from "./vendor/color.js";
|
|
3
|
+
import { stockLights } from "./vendor/plastic.js";
|
|
4
4
|
|
|
5
5
|
const contrast = (a: number, b: number) => (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05);
|
|
6
6
|
|
|
7
7
|
/** Off-black or off-white eyes, whichever reads stronger on the body: the vendor's fixed cutoff left 2:1 eyes on mid blues. */
|
|
8
8
|
export function inkFor(body: string): string {
|
|
9
9
|
const l = luminance(body);
|
|
10
|
-
return contrast(l, luminance(DARK_INK)) >= contrast(l, luminance(LIGHT_INK))
|
|
10
|
+
return contrast(l, luminance(DARK_INK)) >= contrast(l, luminance(LIGHT_INK))
|
|
11
|
+
? DARK_INK
|
|
12
|
+
: LIGHT_INK;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
export const clamp = (v: number, lo: number, hi: number) =>
|
|
@@ -16,7 +18,7 @@ export const q = (v: number, lo: number, hi: number) => Math.round(clamp(v, lo,
|
|
|
16
18
|
export const clampOpt = (v: number | undefined, d: number, lo: number, hi: number) =>
|
|
17
19
|
clamp(v ?? d, lo, hi);
|
|
18
20
|
export const deviceDpr = () =>
|
|
19
|
-
Math.min(2, (typeof devicePixelRatio ===
|
|
21
|
+
Math.min(2, (typeof devicePixelRatio === "number" && devicePixelRatio) || 1);
|
|
20
22
|
|
|
21
23
|
export function hashSeed(id: string): number {
|
|
22
24
|
let h = 2166136261;
|
|
@@ -25,20 +27,23 @@ export function hashSeed(id: string): number {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
export const reducedMotion = (): boolean =>
|
|
28
|
-
typeof matchMedia ===
|
|
30
|
+
typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
29
31
|
|
|
30
|
-
export function resolveTheme(
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
export function resolveTheme(
|
|
33
|
+
theme: "auto" | "dark" | "light",
|
|
34
|
+
el: HTMLElement | null,
|
|
35
|
+
): "dark" | "light" {
|
|
36
|
+
if (theme !== "auto") return theme;
|
|
37
|
+
const host = el?.closest("[data-theme], .dark, .light") as HTMLElement | null;
|
|
33
38
|
if (host) {
|
|
34
|
-
const v = host.getAttribute(
|
|
35
|
-
if (v ===
|
|
36
|
-
if (host.classList.contains(
|
|
37
|
-
if (host.classList.contains(
|
|
39
|
+
const v = host.getAttribute("data-theme");
|
|
40
|
+
if (v === "dark" || v === "light") return v;
|
|
41
|
+
if (host.classList.contains("dark")) return "dark";
|
|
42
|
+
if (host.classList.contains("light")) return "light";
|
|
38
43
|
}
|
|
39
|
-
return typeof matchMedia ===
|
|
40
|
-
?
|
|
41
|
-
:
|
|
44
|
+
return typeof matchMedia === "function" && matchMedia("(prefers-color-scheme: light)").matches
|
|
45
|
+
? "light"
|
|
46
|
+
: "dark";
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
export function lightsFor(lightAt: number, backLight?: number, lightFront?: number) {
|
|
@@ -46,12 +51,13 @@ export function lightsFor(lightAt: number, backLight?: number, lightFront?: numb
|
|
|
46
51
|
const b = ((backLight ?? 0) * Math.PI) / 180;
|
|
47
52
|
const lights = stockLights(Math.sin(a), -Math.cos(a));
|
|
48
53
|
if (backLight !== undefined) [lights.bx, lights.by] = [Math.sin(b), -Math.cos(b)];
|
|
49
|
-
if (lightFront !== undefined)
|
|
54
|
+
if (lightFront !== undefined)
|
|
55
|
+
lights.front = (Math.min(85, Math.max(0, lightFront)) * Math.PI) / 180;
|
|
50
56
|
return lights;
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
export function warmIdle(fn: () => void): () => void {
|
|
54
|
-
if (typeof requestIdleCallback ===
|
|
60
|
+
if (typeof requestIdleCallback === "function") {
|
|
55
61
|
const id = requestIdleCallback(fn);
|
|
56
62
|
return () => cancelIdleCallback(id);
|
|
57
63
|
}
|
package/src/agents/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { default as AgentAvatar } from
|
|
2
|
-
export { default as AgentCast } from
|
|
3
|
-
export type { Agent, AgentAvatarProps, AgentShape } from
|
|
1
|
+
export { default as AgentAvatar } from "./agent-avatar.svelte";
|
|
2
|
+
export { default as AgentCast } from "./agent-cast.svelte";
|
|
3
|
+
export type { Agent, AgentAvatarProps, AgentShape } from "./types.js";
|
|
4
4
|
export {
|
|
5
5
|
agentPresets,
|
|
6
6
|
agentShapes,
|
|
@@ -8,4 +8,4 @@ export {
|
|
|
8
8
|
agentStates,
|
|
9
9
|
agentPalette,
|
|
10
10
|
agentStateLabels,
|
|
11
|
-
} from
|
|
11
|
+
} from "./types.js";
|
package/src/agents/page-state.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* What every avatar on the page shares: the batching shown-gate, so a row of
|
|
2
2
|
them comes in together, the path caches, and one theme watcher. */
|
|
3
|
-
import { bakesPending } from
|
|
3
|
+
import { bakesPending } from "./vendor/plastic.js";
|
|
4
4
|
|
|
5
5
|
export const SHOW_WITHIN = 4000;
|
|
6
6
|
export const waiters = new Map<object, { ready: () => boolean; show: () => void }>();
|
|
@@ -45,19 +45,19 @@ const themeListeners = new Set<() => void>();
|
|
|
45
45
|
let themeWatch: (() => void) | null = null;
|
|
46
46
|
export function onThemeChange(fn: () => void): () => void {
|
|
47
47
|
themeListeners.add(fn);
|
|
48
|
-
if (!themeWatch && typeof MutationObserver ===
|
|
48
|
+
if (!themeWatch && typeof MutationObserver === "function" && typeof document !== "undefined") {
|
|
49
49
|
const fire = () => {
|
|
50
50
|
for (const l of themeListeners) l();
|
|
51
51
|
};
|
|
52
52
|
const mo = new MutationObserver(fire);
|
|
53
|
-
const opts = { attributes: true, attributeFilter: [
|
|
53
|
+
const opts = { attributes: true, attributeFilter: ["class", "data-theme"] };
|
|
54
54
|
mo.observe(document.documentElement, opts);
|
|
55
55
|
if (document.body) mo.observe(document.body, opts);
|
|
56
|
-
const mq = typeof matchMedia ===
|
|
57
|
-
mq?.addEventListener(
|
|
56
|
+
const mq = typeof matchMedia === "function" ? matchMedia("(prefers-color-scheme: dark)") : null;
|
|
57
|
+
mq?.addEventListener("change", fire);
|
|
58
58
|
themeWatch = () => {
|
|
59
59
|
mo.disconnect();
|
|
60
|
-
mq?.removeEventListener(
|
|
60
|
+
mq?.removeEventListener("change", fire);
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
return () => {
|
package/src/agents/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BotAvatarFace, BotAvatarProps, BotAvatarType } from
|
|
1
|
+
import type { BotAvatarFace, BotAvatarProps, BotAvatarType } from "./vendor/types.js";
|
|
2
2
|
|
|
3
3
|
/** The body shapes an agent can be drawn as. */
|
|
4
4
|
export type AgentShape = BotAvatarType;
|
|
@@ -11,7 +11,7 @@ export type {
|
|
|
11
11
|
BotAvatarHat as AgentHat,
|
|
12
12
|
BotAvatarGlasses as AgentGlasses,
|
|
13
13
|
BotAvatarPreset as AgentPreset,
|
|
14
|
-
} from
|
|
14
|
+
} from "./vendor/types.js";
|
|
15
15
|
|
|
16
16
|
export {
|
|
17
17
|
botAvatarPresets as agentPresets,
|
|
@@ -20,7 +20,7 @@ export {
|
|
|
20
20
|
botAvatarStates as agentStates,
|
|
21
21
|
botAvatarPalette as agentPalette,
|
|
22
22
|
stateLabels as agentStateLabels,
|
|
23
|
-
} from
|
|
23
|
+
} from "./vendor/presets.js";
|
|
24
24
|
|
|
25
25
|
/** One member of a cast: a name, a role, and the face they draw. */
|
|
26
26
|
export type Agent = {
|
|
@@ -51,7 +51,7 @@ type KnownProps<T> = {
|
|
|
51
51
|
*/
|
|
52
52
|
export type AgentAvatarProps = Omit<
|
|
53
53
|
KnownProps<BotAvatarProps>,
|
|
54
|
-
|
|
54
|
+
"type" | "face" | "ink" | "size" | "className" | "style"
|
|
55
55
|
> & {
|
|
56
56
|
/** Display name, for the default aria-label. */
|
|
57
57
|
name?: string;
|
|
@@ -68,7 +68,7 @@ export type AgentAvatarProps = Omit<
|
|
|
68
68
|
class?: string;
|
|
69
69
|
style?: string;
|
|
70
70
|
onclick?: (event: MouseEvent) => void;
|
|
71
|
-
|
|
71
|
+
"aria-label"?: string;
|
|
72
72
|
/** Hide the canvas from assistive tech when a parent already names the agent. */
|
|
73
|
-
|
|
73
|
+
"aria-hidden"?: boolean | "true" | "false";
|
|
74
74
|
};
|
|
@@ -50,12 +50,8 @@
|
|
|
50
50
|
size="sm"
|
|
51
51
|
icon
|
|
52
52
|
disabled={disabled || status === "processing"}
|
|
53
|
-
|
|
54
|
-
class={cn(
|
|
55
|
-
"relative",
|
|
56
|
-
status === "processing" && "pointer-events-none",
|
|
57
|
-
className,
|
|
58
|
-
)}
|
|
53
|
+
{onclick}
|
|
54
|
+
class={cn("relative", status === "processing" && "pointer-events-none", className)}
|
|
59
55
|
>
|
|
60
56
|
{#if status === "processing"}
|
|
61
57
|
<Spinner class="size-4" />
|
|
@@ -68,12 +64,8 @@
|
|
|
68
64
|
{variant}
|
|
69
65
|
{size}
|
|
70
66
|
disabled={disabled || status === "processing"}
|
|
71
|
-
|
|
72
|
-
class={cn(
|
|
73
|
-
"gap-1.5",
|
|
74
|
-
status === "processing" && "pointer-events-none",
|
|
75
|
-
className,
|
|
76
|
-
)}
|
|
67
|
+
{onclick}
|
|
68
|
+
class={cn("gap-1.5", status === "processing" && "pointer-events-none", className)}
|
|
77
69
|
>
|
|
78
70
|
{#if status === "processing"}
|
|
79
71
|
<Spinner class="size-3.5" />
|
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
// DERIVED
|
|
42
42
|
// =========================
|
|
43
43
|
let heading = $derived(label || "Generating");
|
|
44
|
-
let percent = $derived(
|
|
44
|
+
let percent = $derived(
|
|
45
|
+
progress && progress.total > 0 ? (progress.completed / progress.total) * 100 : 0,
|
|
46
|
+
);
|
|
45
47
|
|
|
46
48
|
// =========================
|
|
47
49
|
// EFFECTS
|
|
@@ -82,7 +84,9 @@
|
|
|
82
84
|
<!-- #key is the reflow: Svelte drops the node and builds a new one,
|
|
83
85
|
which is what replays the pop-in on every step. -->
|
|
84
86
|
{#key progress.completed}
|
|
85
|
-
<span class="t-digit-group is-animating"
|
|
87
|
+
<span class="t-digit-group is-animating"
|
|
88
|
+
><span class="t-digit">{progress.completed}</span></span
|
|
89
|
+
>
|
|
86
90
|
{/key}<span class="gen-total">/{progress.total}</span>
|
|
87
91
|
</span>
|
|
88
92
|
{/if}
|
|
@@ -93,7 +97,10 @@
|
|
|
93
97
|
</div>
|
|
94
98
|
|
|
95
99
|
<div class="gen-track" data-indeterminate={progress ? undefined : true}>
|
|
96
|
-
<div
|
|
100
|
+
<div
|
|
101
|
+
class="gen-fill"
|
|
102
|
+
style:transform={progress ? `scaleX(${percent / 100})` : undefined}
|
|
103
|
+
></div>
|
|
97
104
|
</div>
|
|
98
105
|
|
|
99
106
|
{#if progress?.currentStep}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
/* WHY:
|
|
2
|
-
|
|
3
|
-
:global() while the parent class stays component-scoped. */
|
|
1
|
+
/* WHY: Svelte never scopes marked's {@html} output, so the caret reaches its last child
|
|
2
|
+
with :global() while the parent class stays scoped. */
|
|
4
3
|
.ai-response.is-streaming > :last-child::after {
|
|
5
4
|
content: "";
|
|
6
5
|
display: inline-block;
|
|
@@ -2,22 +2,8 @@
|
|
|
2
2
|
/* Source: https://github.com/Jakubantalik/transitions.dev */
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
badge, button). Bring your own size, shape, and stacking;
|
|
8
|
-
this stylesheet only owns the hover transform + transition.
|
|
9
|
-
|
|
10
|
-
<div class="t-avatar-group">
|
|
11
|
-
<div class="t-avatar">…</div>
|
|
12
|
-
<div class="t-avatar">…</div>
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
Wire-up (JS):
|
|
16
|
-
On mouseenter of any .t-avatar, walk every sibling and set
|
|
17
|
-
inline --shift and --scale-active with a distance falloff.
|
|
18
|
-
Set transition-timing-function inline BEFORE the variable
|
|
19
|
-
writes — --avatar-ease-in on hover-in, --avatar-ease-out on
|
|
20
|
-
the root's mouseleave.
|
|
5
|
+
JS sets each sibling's --shift and --scale-active on hover, and must set
|
|
6
|
+
transition-timing-function inline before those writes, or the ease is wrong.
|
|
21
7
|
*/
|
|
22
8
|
|
|
23
9
|
:root {
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
/* Card hover tilt
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
and --tilt-gx/gy, adds `.is-tilting` while moving and `.is-hover` for the
|
|
5
|
-
glare. Return and glare clocks have no token at their length, by design:
|
|
6
|
-
the settle is meant to read slower than any surface. */
|
|
1
|
+
/* Card hover tilt, transitions.dev `3d-tilt`: bind pointermove to the flat outer
|
|
2
|
+
`.t-tilt`, never the card, or its rotating edges slip under the cursor and the
|
|
3
|
+
hover flickers. */
|
|
7
4
|
:root {
|
|
8
5
|
--tilt-perspective: 1000px;
|
|
9
6
|
--tilt-return: 1000ms;
|
|
@@ -2,21 +2,8 @@
|
|
|
2
2
|
/* Source: https://github.com/Jakubantalik/transitions.dev */
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
<span class="t-digit">1</span>
|
|
8
|
-
<span class="t-digit">2</span>
|
|
9
|
-
<span class="t-digit" data-stagger="1">.</span>
|
|
10
|
-
<span class="t-digit" data-stagger="2">3</span>
|
|
11
|
-
</span>
|
|
12
|
-
|
|
13
|
-
Replay:
|
|
14
|
-
Remove `.is-animating`, re-render digits (or swap text),
|
|
15
|
-
force a reflow, then re-add `.is-animating`.
|
|
16
|
-
|
|
17
|
-
Direction:
|
|
18
|
-
--digit-dir-x / --digit-dir-y are unit-less multipliers
|
|
19
|
-
(e.g. 1, -1, 0) applied to --digit-distance.
|
|
5
|
+
To replay, remove `.is-animating` from `.t-digit-group`, swap the digits, force a reflow, then
|
|
6
|
+
add it back, or the animation won't restart.
|
|
20
7
|
*/
|
|
21
8
|
|
|
22
9
|
:root {
|
|
@@ -51,18 +51,8 @@
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/* === Extension: bits-ui data-state integration === */
|
|
54
|
-
/* WHY:
|
|
55
|
-
|
|
56
|
-
.t-dropdown on a Popover/Menu/Tooltip Content.
|
|
57
|
-
|
|
58
|
-
WHY "instant-open" is in the list: a tooltip reports three open states, not
|
|
59
|
-
two. It says "delayed-open" when it waited out the hover delay and
|
|
60
|
-
"instant-open" when it skipped that delay, which is every open while
|
|
61
|
-
delayDuration is 0 and every neighbour opened inside the skip window. That
|
|
62
|
-
third name was missing here, so those tooltips mounted, took no open rule,
|
|
63
|
-
and stayed at opacity 0: present in the DOM, never on screen. Found
|
|
64
|
-
11 Sep 2026 in upsys, where the kit's provider defaulted delayDuration to 0
|
|
65
|
-
and so produced nothing but "instant-open". */
|
|
54
|
+
/* WHY: a tooltip has three open states, and without "instant-open" every tooltip
|
|
55
|
+
with delayDuration 0 sat at opacity 0, never on screen (upsys, 11 Sep 2026). */
|
|
66
56
|
.t-dropdown[data-state="open"],
|
|
67
57
|
.t-dropdown[data-state="delayed-open"],
|
|
68
58
|
.t-dropdown[data-state="instant-open"] {
|
|
@@ -111,11 +101,8 @@
|
|
|
111
101
|
}
|
|
112
102
|
}
|
|
113
103
|
|
|
114
|
-
/* A tooltip that skipped its delay skips its entrance too
|
|
115
|
-
|
|
116
|
-
skip window are already open by the time the eye arrives, so animating them
|
|
117
|
-
only adds a wait the delay was there to hide. Scoped to the tooltip slot
|
|
118
|
-
because a menu or popover never reports this state. */
|
|
104
|
+
/* A tooltip that skipped its delay skips its entrance too, since a neighbour opened
|
|
105
|
+
inside the skip window is already there when the eye arrives. */
|
|
119
106
|
[data-slot="tooltip-content"].t-dropdown[data-state="instant-open"] {
|
|
120
107
|
transition: none;
|
|
121
108
|
}
|
|
@@ -2,19 +2,9 @@
|
|
|
2
2
|
/* Source: https://github.com/Jakubantalik/transitions.dev */
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<div class="t-clear-mirror" aria-hidden="true">…</div>
|
|
9
|
-
<div class="t-clear-placeholder" aria-hidden="true">Search</div>
|
|
10
|
-
<div class="t-clear-glow" aria-hidden="true"></div>
|
|
11
|
-
<button class="t-clear-btn" aria-label="Clear">…</button>
|
|
12
|
-
</div>
|
|
13
|
-
|
|
14
|
-
The transitions live in JS (per-frame transform/opacity/filter
|
|
15
|
-
writes): the streak envelope and per-word gradient stack cannot
|
|
16
|
-
be expressed as static @keyframes. This stylesheet only owns the
|
|
17
|
-
resting state + the variables JS reads.
|
|
5
|
+
The clear runs in JS, since its per-word streak can't be static
|
|
6
|
+
@keyframes, so this file owns only the resting state and the
|
|
7
|
+
variables JS reads.
|
|
18
8
|
*/
|
|
19
9
|
|
|
20
10
|
:root {
|
|
@@ -65,11 +55,8 @@
|
|
|
65
55
|
.t-clear.has-value .t-clear-placeholder {
|
|
66
56
|
opacity: 0;
|
|
67
57
|
}
|
|
68
|
-
/*
|
|
69
|
-
|
|
70
|
-
then animates opacity. mix-blend-mode: multiply darkens the
|
|
71
|
-
underlying input; flip to screen in dark mode so the same
|
|
72
|
-
alpha values lighten instead of vanish. */
|
|
58
|
+
/* JS paints the streak's gradients here during a clear; dark mode
|
|
59
|
+
flips multiply to screen so the same alphas lighten, not vanish. */
|
|
73
60
|
.t-clear-glow {
|
|
74
61
|
position: absolute;
|
|
75
62
|
inset: 0;
|
|
@@ -2,34 +2,9 @@
|
|
|
2
2
|
/* Source: https://github.com/Jakubantalik/transitions.dev */
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
bordered wrapper, whatever owns the visible border),
|
|
9
|
-
and .t-error-msg to the message you want to reveal.
|
|
10
|
-
Bring your own sizing, padding, border colors, and
|
|
11
|
-
typography.
|
|
12
|
-
|
|
13
|
-
<div class="t-input-wrap">
|
|
14
|
-
<div class="t-input">
|
|
15
|
-
<input type="text">
|
|
16
|
-
</div>
|
|
17
|
-
<p class="t-error-msg">Please enter a valid email.</p>
|
|
18
|
-
</div>
|
|
19
|
-
|
|
20
|
-
Trigger:
|
|
21
|
-
Add `.is-error` to .t-input-wrap and .t-input. Your
|
|
22
|
-
own border-color rules drive the visible color; this
|
|
23
|
-
stylesheet only owns the tween.
|
|
24
|
-
Restart the shake by removing `.is-shaking` from
|
|
25
|
-
.t-input, forcing a reflow, then re-adding it.
|
|
26
|
-
Optional: after --revert-hold ms, drop both
|
|
27
|
-
`.is-error` classes so border and message fade back
|
|
28
|
-
to neutral over --revert-dur.
|
|
29
|
-
|
|
30
|
-
Per-segment ease: each keyframe stop carries its own
|
|
31
|
-
animation-timing-function so each leg follows the Figma
|
|
32
|
-
cubic-bezier curve independently.
|
|
5
|
+
Put .is-error on .t-input-wrap and .t-input, and restart the
|
|
6
|
+
shake by removing `.is-shaking` from .t-input, forcing a
|
|
7
|
+
reflow, then re-adding it.
|
|
33
8
|
*/
|
|
34
9
|
|
|
35
10
|
:root {
|
|
@@ -42,10 +17,8 @@
|
|
|
42
17
|
--revert-dur: 280ms;
|
|
43
18
|
}
|
|
44
19
|
|
|
45
|
-
/*
|
|
46
|
-
|
|
47
|
-
only owns the interpolation. Use a constant border-width
|
|
48
|
-
across states so the tween never shifts inner content. */
|
|
20
|
+
/* This rule owns only the border-color tween, so keep the
|
|
21
|
+
border-width constant across states or the content shifts. */
|
|
49
22
|
.t-input {
|
|
50
23
|
transition: border-color 150ms ease-out;
|
|
51
24
|
will-change: transform;
|
|
@@ -57,10 +30,8 @@
|
|
|
57
30
|
transition: border-color var(--revert-dur, 280ms) ease-out;
|
|
58
31
|
}
|
|
59
32
|
|
|
60
|
-
/*
|
|
61
|
-
|
|
62
|
-
fade-out. Entering .is-error drops the delay to 0 so the
|
|
63
|
-
message becomes visible immediately. */
|
|
33
|
+
/* Hiding delays visibility by --revert-dur so the message stays
|
|
34
|
+
painted through its fade; .is-error drops the delay to 0. */
|
|
64
35
|
.t-error-msg {
|
|
65
36
|
opacity: 0;
|
|
66
37
|
visibility: hidden;
|
|
@@ -76,11 +47,8 @@
|
|
|
76
47
|
visibility 0s linear 0s;
|
|
77
48
|
}
|
|
78
49
|
|
|
79
|
-
/*
|
|
80
|
-
|
|
81
|
-
%-stops are cumulative durations as a fraction of the
|
|
82
|
-
total (80, 60, 80, 60 = 280ms): 28.57%, 57.14%, 78.57%,
|
|
83
|
-
100%. Recompute if any segment duration changes. */
|
|
50
|
+
/* The %-stops are cumulative fractions of 280ms (80, 60, 80,
|
|
51
|
+
60), so recompute them if any segment's duration changes. */
|
|
84
52
|
.t-input.is-shaking {
|
|
85
53
|
animation: t-input-shake calc(var(--shake-dur-a) * 2 + var(--shake-dur-b) * 2) linear;
|
|
86
54
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
/* Learn more hover
|
|
2
|
-
|
|
3
|
-
apart about the apex, so the arrow leans into the move. Pure CSS.
|
|
4
|
-
`transform-box: view-box` is what makes the arm origin resolve against
|
|
5
|
-
the viewBox rather than each path's own bounding box. */
|
|
1
|
+
/* Learn more hover, transitions.dev 24: `transform-box: view-box` makes the arm origin
|
|
2
|
+
resolve against the viewBox, not each path's own bounding box. */
|
|
6
3
|
:root {
|
|
7
4
|
--learn-shift: 2px;
|
|
8
5
|
--learn-spread: 8deg;
|
|
@@ -22,23 +19,34 @@
|
|
|
22
19
|
vector-effect: non-scaling-stroke;
|
|
23
20
|
transition: transform var(--learn-out) var(--learn-ease);
|
|
24
21
|
}
|
|
25
|
-
.t-learn:hover .t-learn-chevron,
|
|
26
22
|
.t-learn:focus-visible .t-learn-chevron {
|
|
27
23
|
transform: translateX(var(--learn-shift));
|
|
28
24
|
transition-duration: var(--learn-in);
|
|
29
25
|
}
|
|
30
|
-
.t-learn:hover .t-learn-arm,
|
|
31
26
|
.t-learn:focus-visible .t-learn-arm {
|
|
32
27
|
transition-duration: var(--learn-in);
|
|
33
28
|
}
|
|
34
|
-
.t-learn:hover .t-learn-arm-top,
|
|
35
29
|
.t-learn:focus-visible .t-learn-arm-top {
|
|
36
30
|
transform: rotate(var(--learn-spread));
|
|
37
31
|
}
|
|
38
|
-
.t-learn:hover .t-learn-arm-bot,
|
|
39
32
|
.t-learn:focus-visible .t-learn-arm-bot {
|
|
40
33
|
transform: rotate(calc(var(--learn-spread) * -1));
|
|
41
34
|
}
|
|
35
|
+
@media (hover: hover) and (pointer: fine) {
|
|
36
|
+
.t-learn:hover .t-learn-chevron {
|
|
37
|
+
transform: translateX(var(--learn-shift));
|
|
38
|
+
transition-duration: var(--learn-in);
|
|
39
|
+
}
|
|
40
|
+
.t-learn:hover .t-learn-arm {
|
|
41
|
+
transition-duration: var(--learn-in);
|
|
42
|
+
}
|
|
43
|
+
.t-learn:hover .t-learn-arm-top {
|
|
44
|
+
transform: rotate(var(--learn-spread));
|
|
45
|
+
}
|
|
46
|
+
.t-learn:hover .t-learn-arm-bot {
|
|
47
|
+
transform: rotate(calc(var(--learn-spread) * -1));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
42
50
|
|
|
43
51
|
@media (prefers-reduced-motion: reduce) {
|
|
44
52
|
.t-learn-chevron,
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
/* Like button
|
|
2
|
-
|
|
3
|
-
one particle duration to fire the spray, writing --px/--py/--pdur/--pdelay
|
|
4
|
-
per dot in JS so no two bursts match. */
|
|
1
|
+
/* Like button, transitions.dev 23. For the spray, JS writes --px/--py/--pdur/--pdelay
|
|
2
|
+
per dot while `.is-bursting` is on, so no two bursts match. */
|
|
5
3
|
:root {
|
|
6
4
|
--like-color: #f40051;
|
|
7
5
|
--like-fill: var(--duration-quick, 150ms);
|
|
@@ -2,16 +2,8 @@
|
|
|
2
2
|
/* Source: https://github.com/Jakubantalik/transitions.dev */
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
<section class="t-page" data-page-id="1">…</section>
|
|
8
|
-
<section class="t-page" data-page-id="2">…</section>
|
|
9
|
-
</div>
|
|
10
|
-
|
|
11
|
-
State:
|
|
12
|
-
Set data-page="1" or "2" on .t-page-slide.
|
|
13
|
-
Page 1 exits to the left, page 2 exits to the right.
|
|
14
|
-
--page-exit-enabled (0/1) disables the outgoing slide.
|
|
5
|
+
Set data-page="1" or "2" on .t-page-slide, which holds two .t-page
|
|
6
|
+
sections with data-page-id; --page-exit-enabled: 0 turns off the outgoing slide.
|
|
15
7
|
*/
|
|
16
8
|
|
|
17
9
|
:root {
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
plus and the menu cross-fade through a blur. Set the open footprint on the
|
|
4
|
-
consumer side; the two sizes here are the upstream demo's. Use `dropdown.css`
|
|
5
|
-
instead when the surface is a separate popover that merely grows. */
|
|
1
|
+
/* transitions.dev `dropdown-menu-morph`: the trigger itself becomes the menu. Set the open
|
|
2
|
+
size on the consumer side, since these sizes are the upstream demo's. */
|
|
6
3
|
:root {
|
|
7
4
|
--morph-open-dur: var(--duration-medium, 350ms);
|
|
8
5
|
--morph-close-dur: var(--duration-fast, 250ms);
|
|
@@ -2,17 +2,9 @@
|
|
|
2
2
|
/* Source: https://github.com/Jakubantalik/transitions.dev */
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
in sync if the text changes.
|
|
9
|
-
|
|
10
|
-
<span class="t-shimmer" data-text="Planning next moves">
|
|
11
|
-
Planning next moves
|
|
12
|
-
</span>
|
|
13
|
-
|
|
14
|
-
Pure CSS — no JS. Tune --shimmer-base / --shimmer-highlight in
|
|
15
|
-
your own theme rules so the colors follow light / dark mode.
|
|
5
|
+
Copy the visible text into data-text and keep the two in sync, or the ::before
|
|
6
|
+
gradient lands on the wrong glyphs:
|
|
7
|
+
<span class="t-shimmer" data-text="Planning">Planning</span>
|
|
16
8
|
*/
|
|
17
9
|
|
|
18
10
|
:root {
|
|
@@ -23,13 +15,8 @@
|
|
|
23
15
|
--shimmer-ease: var(--ease-linear, linear);
|
|
24
16
|
}
|
|
25
17
|
|
|
26
|
-
/*
|
|
27
|
-
|
|
28
|
-
2. ::before duplicates it via content: attr(data-text),
|
|
29
|
-
paints a transparent → highlight → transparent gradient
|
|
30
|
-
onto it, and clips that gradient to the glyphs via
|
|
31
|
-
background-clip: text. Animating background-position
|
|
32
|
-
sweeps the band across the text. */
|
|
18
|
+
/* ::before repeats the text from data-text and clips a moving gradient band to its
|
|
19
|
+
glyphs with background-clip: text. */
|
|
33
20
|
.t-shimmer {
|
|
34
21
|
position: relative;
|
|
35
22
|
display: inline-block;
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
/* Spinning counter
|
|
2
|
-
|
|
3
|
-
(spins * 10 + digit) cells and staggers the columns. The motion streak is an
|
|
4
|
-
SVG feGaussianBlur with stdDeviation="0 Y" decayed per column: a CSS blur()
|
|
5
|
-
is isotropic and would smear the digit sideways. Use `digit-pop-in.css` when
|
|
6
|
-
a number simply updates in place. */
|
|
1
|
+
/* Spinning counter, transitions.dev 26: the streak is an SVG feGaussianBlur with
|
|
2
|
+
stdDeviation="0 Y" because a CSS blur() is isotropic and would smear digits sideways. */
|
|
7
3
|
:root {
|
|
8
4
|
--reel-dur: 1400ms;
|
|
9
5
|
--reel-cell: 30px;
|
|
@@ -2,21 +2,8 @@
|
|
|
2
2
|
/* Source: https://github.com/Jakubantalik/transitions.dev */
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The wrapper drives fade + rotate + blur + Y-bob; if your
|
|
8
|
-
icon is an SVG <path>, it gets the stroke-draw animation.
|
|
9
|
-
|
|
10
|
-
<span class="t-success-check" data-state="out" aria-hidden="true">
|
|
11
|
-
<svg viewBox="0 0 48 48" fill="none">…</svg>
|
|
12
|
-
</span>
|
|
13
|
-
|
|
14
|
-
Trigger:
|
|
15
|
-
Cold load is data-state="out" (opacity 0; no animation).
|
|
16
|
-
Show: set data-state="in".
|
|
17
|
-
|
|
18
|
-
Replace the stroke-dasharray placeholder (20) with the result
|
|
19
|
-
of path.getTotalLength() for your path, or set it inline in JS.
|
|
5
|
+
Wrap the icon in .t-success-check and flip data-state from "out" to "in".
|
|
6
|
+
Replace the stroke-dasharray placeholder (20) with your path's getTotalLength().
|
|
20
7
|
*/
|
|
21
8
|
|
|
22
9
|
:root {
|