@fungi.computer/caps 0.0.0-stage → 0.0.1
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/LICENSE +21 -0
- package/README.md +1125 -2
- package/dist/blocks/app-bar.d.ts +43 -0
- package/dist/blocks/app-bar.js +244 -0
- package/dist/blocks/app-status-bar.d.ts +93 -0
- package/dist/blocks/app-status-bar.js +42 -0
- package/dist/blocks/async-state.d.ts +21 -0
- package/dist/blocks/async-state.js +8 -0
- package/dist/blocks/card-grid.d.ts +11 -0
- package/dist/blocks/card-grid.js +21 -0
- package/dist/blocks/command-menu.d.ts +26 -0
- package/dist/blocks/command-menu.js +70 -0
- package/dist/blocks/composer.d.ts +23 -0
- package/dist/blocks/composer.js +13 -0
- package/dist/blocks/empty-state.d.ts +59 -0
- package/dist/blocks/empty-state.js +35 -0
- package/dist/blocks/faq-chat.d.ts +62 -0
- package/dist/blocks/faq-chat.js +77 -0
- package/dist/blocks/game-share-card.d.ts +17 -0
- package/dist/blocks/game-share-card.js +9 -0
- package/dist/blocks/launcher-grid.d.ts +50 -0
- package/dist/blocks/launcher-grid.js +11 -0
- package/dist/blocks/listing-detail.d.ts +23 -0
- package/dist/blocks/listing-detail.js +12 -0
- package/dist/blocks/loading-state.d.ts +5 -0
- package/dist/blocks/loading-state.js +8 -0
- package/dist/blocks/mosaic.d.ts +29 -0
- package/dist/blocks/mosaic.js +19 -0
- package/dist/blocks/permission-grid.d.ts +45 -0
- package/dist/blocks/permission-grid.js +14 -0
- package/dist/blocks/pricing-card.d.ts +53 -0
- package/dist/blocks/pricing-card.js +12 -0
- package/dist/blocks/release-tag.d.ts +20 -0
- package/dist/blocks/release-tag.js +10 -0
- package/dist/blocks/resource-select.d.ts +22 -0
- package/dist/blocks/resource-select.js +16 -0
- package/dist/blocks/result-state.d.ts +15 -0
- package/dist/blocks/result-state.js +8 -0
- package/dist/blocks/section-card.d.ts +31 -0
- package/dist/blocks/section-card.js +7 -0
- package/dist/blocks/section-heading.d.ts +13 -0
- package/dist/blocks/section-heading.js +11 -0
- package/dist/blocks/spec-sheet.d.ts +125 -0
- package/dist/blocks/spec-sheet.js +47 -0
- package/dist/blocks/status-tray.d.ts +83 -0
- package/dist/blocks/status-tray.js +79 -0
- package/dist/blocks/upload-queue.d.ts +48 -0
- package/dist/blocks/upload-queue.js +24 -0
- package/dist/components/action-row.d.ts +16 -0
- package/dist/components/action-row.js +11 -0
- package/dist/components/activity-line.d.ts +33 -0
- package/dist/components/activity-line.js +69 -0
- package/dist/components/alert.d.ts +17 -0
- package/dist/components/alert.js +17 -0
- package/dist/components/badge.d.ts +19 -0
- package/dist/components/badge.js +24 -0
- package/dist/components/button.d.ts +55 -0
- package/dist/components/button.js +230 -0
- package/dist/components/card.d.ts +61 -0
- package/dist/components/card.js +48 -0
- package/dist/components/chat-bubble.d.ts +34 -0
- package/dist/components/chat-bubble.js +10 -0
- package/dist/components/checkbox-bead.d.ts +6 -0
- package/dist/components/checkbox-bead.js +67 -0
- package/dist/components/checkbox.d.ts +21 -0
- package/dist/components/checkbox.js +46 -0
- package/dist/components/code-input.d.ts +35 -0
- package/dist/components/code-input.js +126 -0
- package/dist/components/combobox.d.ts +86 -0
- package/dist/components/combobox.js +218 -0
- package/dist/components/confirm-action.d.ts +23 -0
- package/dist/components/confirm-action.js +64 -0
- package/dist/components/copy-field.d.ts +53 -0
- package/dist/components/copy-field.js +49 -0
- package/dist/components/count-badge.d.ts +15 -0
- package/dist/components/count-badge.js +9 -0
- package/dist/components/cover-pattern.d.ts +19 -0
- package/dist/components/cover-pattern.js +74 -0
- package/dist/components/data-list.d.ts +25 -0
- package/dist/components/data-list.js +16 -0
- package/dist/components/dialog.d.ts +39 -0
- package/dist/components/dialog.js +73 -0
- package/dist/components/diff-view.d.ts +14 -0
- package/dist/components/diff-view.js +13 -0
- package/dist/components/disclosure.d.ts +29 -0
- package/dist/components/disclosure.js +19 -0
- package/dist/components/dropdown-menu.d.ts +49 -0
- package/dist/components/dropdown-menu.js +98 -0
- package/dist/components/field-guide.d.ts +41 -0
- package/dist/components/field-guide.js +18 -0
- package/dist/components/field.d.ts +164 -0
- package/dist/components/field.js +228 -0
- package/dist/components/game-feedback.d.ts +84 -0
- package/dist/components/game-feedback.js +48 -0
- package/dist/components/game-hud.d.ts +126 -0
- package/dist/components/game-hud.js +136 -0
- package/dist/components/generation-frame.d.ts +36 -0
- package/dist/components/generation-frame.js +97 -0
- package/dist/components/gooey.d.ts +32 -0
- package/dist/components/gooey.js +25 -0
- package/dist/components/hold-button.d.ts +26 -0
- package/dist/components/hold-button.js +115 -0
- package/dist/components/icon-button.d.ts +24 -0
- package/dist/components/icon-button.js +18 -0
- package/dist/components/icon-checkbox.d.ts +20 -0
- package/dist/components/icon-checkbox.js +9 -0
- package/dist/components/icon-choice-mark.d.ts +6 -0
- package/dist/components/icon-choice-mark.js +5 -0
- package/dist/components/icon-lamp.d.ts +42 -0
- package/dist/components/icon-lamp.js +15 -0
- package/dist/components/icon-radio.d.ts +16 -0
- package/dist/components/icon-radio.js +9 -0
- package/dist/components/inline-code.d.ts +3 -0
- package/dist/components/inline-code.js +7 -0
- package/dist/components/input-group.d.ts +9 -0
- package/dist/components/input-group.js +15 -0
- package/dist/components/input.d.ts +15 -0
- package/dist/components/input.js +15 -0
- package/dist/components/item-grid.d.ts +110 -0
- package/dist/components/item-grid.js +136 -0
- package/dist/components/keycap.d.ts +80 -0
- package/dist/components/keycap.js +18 -0
- package/dist/components/label.d.ts +13 -0
- package/dist/components/label.js +7 -0
- package/dist/components/listbox.d.ts +50 -0
- package/dist/components/listbox.js +134 -0
- package/dist/components/loader-blobs.d.ts +5 -0
- package/dist/components/loader-blobs.js +128 -0
- package/dist/components/loader.d.ts +21 -0
- package/dist/components/loader.js +25 -0
- package/dist/components/markdown.d.ts +23 -0
- package/dist/components/markdown.js +70 -0
- package/dist/components/minimap-labels.d.ts +39 -0
- package/dist/components/minimap-labels.js +113 -0
- package/dist/components/monogram.d.ts +32 -0
- package/dist/components/monogram.js +24 -0
- package/dist/components/motion-visibility.d.ts +2 -0
- package/dist/components/motion-visibility.js +25 -0
- package/dist/components/navigation-rail.d.ts +11 -0
- package/dist/components/navigation-rail.js +55 -0
- package/dist/components/overlay-root.d.ts +16 -0
- package/dist/components/overlay-root.js +24 -0
- package/dist/components/pixel-number.d.ts +50 -0
- package/dist/components/pixel-number.js +113 -0
- package/dist/components/popover.d.ts +31 -0
- package/dist/components/popover.js +24 -0
- package/dist/components/presence.d.ts +59 -0
- package/dist/components/presence.js +232 -0
- package/dist/components/price-tag.d.ts +11 -0
- package/dist/components/price-tag.js +6 -0
- package/dist/components/progress.d.ts +25 -0
- package/dist/components/progress.js +24 -0
- package/dist/components/prose.d.ts +14 -0
- package/dist/components/prose.js +10 -0
- package/dist/components/quota-meter.d.ts +24 -0
- package/dist/components/quota-meter.js +11 -0
- package/dist/components/radio-bead.d.ts +4 -0
- package/dist/components/radio-bead.js +53 -0
- package/dist/components/radio-group.d.ts +54 -0
- package/dist/components/radio-group.js +64 -0
- package/dist/components/resize-handle.d.ts +23 -0
- package/dist/components/resize-handle.js +31 -0
- package/dist/components/rough-drawing.d.ts +42 -0
- package/dist/components/rough-drawing.js +231 -0
- package/dist/components/rough.d.ts +68 -0
- package/dist/components/rough.js +33 -0
- package/dist/components/scroll-area.d.ts +12 -0
- package/dist/components/scroll-area.js +96 -0
- package/dist/components/scroll-motion.d.ts +12 -0
- package/dist/components/scroll-motion.js +31 -0
- package/dist/components/scroll-to-bottom-blob-state.d.ts +40 -0
- package/dist/components/scroll-to-bottom-blob-state.js +109 -0
- package/dist/components/scroll-to-bottom-blob.d.ts +16 -0
- package/dist/components/scroll-to-bottom-blob.js +174 -0
- package/dist/components/select.d.ts +9 -0
- package/dist/components/select.js +12 -0
- package/dist/components/selectable.d.ts +13 -0
- package/dist/components/selectable.js +45 -0
- package/dist/components/send-action.d.ts +33 -0
- package/dist/components/send-action.js +96 -0
- package/dist/components/separator.d.ts +11 -0
- package/dist/components/separator.js +7 -0
- package/dist/components/skeleton.d.ts +5 -0
- package/dist/components/skeleton.js +7 -0
- package/dist/components/slider.d.ts +18 -0
- package/dist/components/slider.js +31 -0
- package/dist/components/stat.d.ts +17 -0
- package/dist/components/stat.js +7 -0
- package/dist/components/status-bead.d.ts +9 -0
- package/dist/components/status-bead.js +107 -0
- package/dist/components/status-mark.d.ts +12 -0
- package/dist/components/status-mark.js +177 -0
- package/dist/components/status.d.ts +38 -0
- package/dist/components/status.js +28 -0
- package/dist/components/store-card.d.ts +21 -0
- package/dist/components/store-card.js +10 -0
- package/dist/components/surface.d.ts +89 -0
- package/dist/components/surface.js +31 -0
- package/dist/components/switch-bead.d.ts +4 -0
- package/dist/components/switch-bead.js +62 -0
- package/dist/components/switch.d.ts +11 -0
- package/dist/components/switch.js +36 -0
- package/dist/components/tabs.d.ts +55 -0
- package/dist/components/tabs.js +81 -0
- package/dist/components/technonomicon.d.ts +192 -0
- package/dist/components/technonomicon.js +121 -0
- package/dist/components/textarea.d.ts +9 -0
- package/dist/components/textarea.js +11 -0
- package/dist/components/toaster.d.ts +4 -0
- package/dist/components/toaster.js +13 -0
- package/dist/components/tool-call-chip.d.ts +22 -0
- package/dist/components/tool-call-chip.js +100 -0
- package/dist/components/tooltip.d.ts +41 -0
- package/dist/components/tooltip.js +169 -0
- package/dist/components/trading-card.d.ts +60 -0
- package/dist/components/trading-card.js +13 -0
- package/dist/components/undo-action.d.ts +52 -0
- package/dist/components/undo-action.js +100 -0
- package/dist/components/undo-toast.d.ts +21 -0
- package/dist/components/undo-toast.js +58 -0
- package/dist/components/visually-hidden.d.ts +9 -0
- package/dist/components/visually-hidden.js +11 -0
- package/dist/components/window.d.ts +65 -0
- package/dist/components/window.js +31 -0
- package/dist/components/wizard.d.ts +17 -0
- package/dist/components/wizard.js +19 -0
- package/dist/enhance/cigarette-card.d.ts +8 -0
- package/dist/enhance/cigarette-card.js +33 -0
- package/dist/enhance/sketch.d.ts +16 -0
- package/dist/enhance/sketch.js +130 -0
- package/dist/form-error.d.ts +7 -0
- package/dist/form-error.js +14 -0
- package/dist/form-fields.d.ts +15 -0
- package/dist/form-fields.js +250 -0
- package/dist/form-schema.d.ts +166 -0
- package/dist/form-schema.js +398 -0
- package/dist/form.d.ts +30 -0
- package/dist/form.js +20 -0
- package/dist/lib/cn.d.ts +8 -0
- package/dist/lib/cn.js +12 -0
- package/dist/lib/format-money.d.ts +2 -0
- package/dist/lib/format-money.js +22 -0
- package/dist/lib/glide.d.ts +12 -0
- package/dist/lib/glide.js +143 -0
- package/dist/lib/ime.d.ts +3 -0
- package/dist/lib/ime.js +8 -0
- package/dist/lib/motion-spring.d.ts +27 -0
- package/dist/lib/motion-spring.js +36 -0
- package/dist/lib/motion.d.ts +51 -0
- package/dist/lib/motion.js +161 -0
- package/dist/lib/reorder-motion.d.ts +13 -0
- package/dist/lib/reorder-motion.js +201 -0
- package/dist/lib/seed-hash.d.ts +6 -0
- package/dist/lib/seed-hash.js +13 -0
- package/dist/lib/tanstack-highlight.d.ts +4 -0
- package/dist/lib/tanstack-highlight.js +41 -0
- package/dist/schema-form.d.ts +120 -0
- package/dist/schema-form.js +129 -0
- package/dist/styles.css +18814 -0
- package/docs/api/README.md +134 -0
- package/docs/api/blocks/app-bar.md +227 -0
- package/docs/api/blocks/app-status-bar.md +257 -0
- package/docs/api/blocks/async-state.md +53 -0
- package/docs/api/blocks/card-grid.md +31 -0
- package/docs/api/blocks/command-menu.md +89 -0
- package/docs/api/blocks/composer.md +40 -0
- package/docs/api/blocks/empty-state.md +97 -0
- package/docs/api/blocks/faq-chat.md +147 -0
- package/docs/api/blocks/game-share-card.md +40 -0
- package/docs/api/blocks/launcher-grid.md +86 -0
- package/docs/api/blocks/listing-detail.md +51 -0
- package/docs/api/blocks/loading-state.md +21 -0
- package/docs/api/blocks/mosaic.md +94 -0
- package/docs/api/blocks/permission-grid.md +79 -0
- package/docs/api/blocks/pricing-card.md +90 -0
- package/docs/api/blocks/release-tag.md +62 -0
- package/docs/api/blocks/resource-select.md +126 -0
- package/docs/api/blocks/result-state.md +42 -0
- package/docs/api/blocks/section-card.md +42 -0
- package/docs/api/blocks/section-heading.md +61 -0
- package/docs/api/blocks/spec-sheet.md +400 -0
- package/docs/api/blocks/status-tray.md +141 -0
- package/docs/api/blocks/upload-queue.md +110 -0
- package/docs/api/components/action-row.md +51 -0
- package/docs/api/components/activity-line.md +103 -0
- package/docs/api/components/alert.md +60 -0
- package/docs/api/components/badge.md +77 -0
- package/docs/api/components/button.md +94 -0
- package/docs/api/components/card.md +165 -0
- package/docs/api/components/chat-bubble.md +66 -0
- package/docs/api/components/checkbox-bead.md +20 -0
- package/docs/api/components/checkbox.md +42 -0
- package/docs/api/components/code-input.md +61 -0
- package/docs/api/components/combobox.md +303 -0
- package/docs/api/components/confirm-action.md +58 -0
- package/docs/api/components/copy-field.md +106 -0
- package/docs/api/components/count-badge.md +39 -0
- package/docs/api/components/cover-pattern.md +43 -0
- package/docs/api/components/data-list.md +80 -0
- package/docs/api/components/dialog.md +235 -0
- package/docs/api/components/diff-view.md +59 -0
- package/docs/api/components/disclosure.md +71 -0
- package/docs/api/components/dropdown-menu.md +269 -0
- package/docs/api/components/field-guide.md +174 -0
- package/docs/api/components/field.md +252 -0
- package/docs/api/components/game-feedback.md +157 -0
- package/docs/api/components/game-hud.md +359 -0
- package/docs/api/components/generation-frame.md +59 -0
- package/docs/api/components/hold-button.md +44 -0
- package/docs/api/components/icon-button.md +56 -0
- package/docs/api/components/icon-checkbox.md +42 -0
- package/docs/api/components/icon-choice-mark.md +31 -0
- package/docs/api/components/icon-lamp.md +92 -0
- package/docs/api/components/icon-radio.md +42 -0
- package/docs/api/components/inline-code.md +21 -0
- package/docs/api/components/input-group.md +53 -0
- package/docs/api/components/input.md +54 -0
- package/docs/api/components/item-grid.md +262 -0
- package/docs/api/components/keycap.md +102 -0
- package/docs/api/components/label.md +40 -0
- package/docs/api/components/listbox.md +131 -0
- package/docs/api/components/loader-blobs.md +9 -0
- package/docs/api/components/loader.md +51 -0
- package/docs/api/components/markdown.md +91 -0
- package/docs/api/components/minimap-labels.md +84 -0
- package/docs/api/components/monogram.md +96 -0
- package/docs/api/components/motion-visibility.md +9 -0
- package/docs/api/components/navigation-rail.md +37 -0
- package/docs/api/components/overlay-root.md +92 -0
- package/docs/api/components/pixel-number.md +120 -0
- package/docs/api/components/popover.md +80 -0
- package/docs/api/components/presence.md +106 -0
- package/docs/api/components/price-tag.md +48 -0
- package/docs/api/components/progress.md +90 -0
- package/docs/api/components/prose.md +48 -0
- package/docs/api/components/quota-meter.md +47 -0
- package/docs/api/components/radio-bead.md +9 -0
- package/docs/api/components/radio-group.md +126 -0
- package/docs/api/components/resize-handle.md +46 -0
- package/docs/api/components/rough-drawing.md +122 -0
- package/docs/api/components/rough.md +66 -0
- package/docs/api/components/scroll-area.md +22 -0
- package/docs/api/components/scroll-motion.md +9 -0
- package/docs/api/components/scroll-to-bottom-blob-state.md +162 -0
- package/docs/api/components/scroll-to-bottom-blob.md +73 -0
- package/docs/api/components/select.md +39 -0
- package/docs/api/components/send-action.md +58 -0
- package/docs/api/components/separator.md +38 -0
- package/docs/api/components/skeleton.md +31 -0
- package/docs/api/components/slider.md +70 -0
- package/docs/api/components/stat.md +42 -0
- package/docs/api/components/status-bead.md +19 -0
- package/docs/api/components/status-mark.md +19 -0
- package/docs/api/components/status.md +105 -0
- package/docs/api/components/store-card.md +53 -0
- package/docs/api/components/surface.md +161 -0
- package/docs/api/components/switch-bead.md +9 -0
- package/docs/api/components/switch.md +40 -0
- package/docs/api/components/tabs.md +138 -0
- package/docs/api/components/technonomicon.md +773 -0
- package/docs/api/components/textarea.md +40 -0
- package/docs/api/components/toaster.md +29 -0
- package/docs/api/components/tool-call-chip.md +68 -0
- package/docs/api/components/tooltip.md +113 -0
- package/docs/api/components/trading-card.md +95 -0
- package/docs/api/components/undo-action.md +117 -0
- package/docs/api/components/undo-toast.md +49 -0
- package/docs/api/components/visually-hidden.md +37 -0
- package/docs/api/components/window.md +291 -0
- package/docs/api/components/wizard.md +65 -0
- package/docs/api/enhance/cigarette-card.md +52 -0
- package/docs/api/enhance/sketch.md +42 -0
- package/docs/api/form.md +1623 -0
- package/docs/api/lib/cn.md +46 -0
- package/docs/api/lib/format-money.md +30 -0
- package/docs/api/lib/glide.md +36 -0
- package/docs/api/lib/ime.md +29 -0
- package/docs/api/lib/motion-spring.md +91 -0
- package/docs/api/lib/motion.md +212 -0
- package/docs/api/lib/reorder-motion.md +46 -0
- package/docs/api/lib/seed-hash.md +31 -0
- package/docs/api/lib/tanstack-highlight.md +40 -0
- package/package.json +597 -3
- package/src/app-status-bar.css +158 -0
- package/src/fonts.css +1 -0
- package/src/status-tray.css +282 -0
- package/src/styles.css +10177 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type EasingParam } from "animejs";
|
|
2
|
+
import { type Motion } from "./motion.js";
|
|
3
|
+
/** Anime.js timing for one tween or segment. */
|
|
4
|
+
export type MotionTiming = Readonly<{
|
|
5
|
+
ease: EasingParam;
|
|
6
|
+
duration: number;
|
|
7
|
+
}>;
|
|
8
|
+
/** Timing for a change that must land at once. */
|
|
9
|
+
export declare const immediateTiming: MotionTiming;
|
|
10
|
+
/** A component's own spring, as authored for today's default feel. */
|
|
11
|
+
export type AuthoredSpring = Readonly<{
|
|
12
|
+
bounce: number;
|
|
13
|
+
duration: number;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Anime.js timing for an authored spring, in the theme's feel: bounce and
|
|
17
|
+
* settle time scale with `--stipe-motion-bounce` and
|
|
18
|
+
* `--stipe-motion-spring-duration`, and a stepped theme moves in
|
|
19
|
+
* `--stipe-motion-steps` discrete steps instead. Today's themes reproduce the
|
|
20
|
+
* authored spring exactly.
|
|
21
|
+
*/
|
|
22
|
+
export declare function themedSpring(motion: Motion, authored: AuthoredSpring): MotionTiming;
|
|
23
|
+
/**
|
|
24
|
+
* Anime.js timing for an authored eased segment: the duration scales with the
|
|
25
|
+
* theme's tempo, and a stepped theme replaces the curve with steps.
|
|
26
|
+
*/
|
|
27
|
+
export declare function themedEase(motion: Motion, authored: MotionTiming): MotionTiming;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { spring, steps } from "animejs";
|
|
2
|
+
import { motionBounce, motionSpringTime, motionTime, } from "./motion.js";
|
|
3
|
+
/** Timing for a change that must land at once. */
|
|
4
|
+
export const immediateTiming = Object.freeze({
|
|
5
|
+
ease: "linear",
|
|
6
|
+
duration: 0,
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* Anime.js timing for an authored spring, in the theme's feel: bounce and
|
|
10
|
+
* settle time scale with `--stipe-motion-bounce` and
|
|
11
|
+
* `--stipe-motion-spring-duration`, and a stepped theme moves in
|
|
12
|
+
* `--stipe-motion-steps` discrete steps instead. Today's themes reproduce the
|
|
13
|
+
* authored spring exactly.
|
|
14
|
+
*/
|
|
15
|
+
export function themedSpring(motion, authored) {
|
|
16
|
+
const duration = motionSpringTime(motion, authored.duration);
|
|
17
|
+
if (duration <= 0)
|
|
18
|
+
return immediateTiming;
|
|
19
|
+
if (motion.steps > 0)
|
|
20
|
+
return { ease: steps(motion.steps), duration };
|
|
21
|
+
return {
|
|
22
|
+
ease: spring({ bounce: motionBounce(motion, authored.bounce), duration }),
|
|
23
|
+
duration,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Anime.js timing for an authored eased segment: the duration scales with the
|
|
28
|
+
* theme's tempo, and a stepped theme replaces the curve with steps.
|
|
29
|
+
*/
|
|
30
|
+
export function themedEase(motion, authored) {
|
|
31
|
+
const duration = motionTime(motion, authored.duration);
|
|
32
|
+
return {
|
|
33
|
+
ease: motion.steps > 0 ? steps(motion.steps) : authored.ease,
|
|
34
|
+
duration,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
/** Resolved, element-scoped motion. Times are milliseconds and distances pixels. */
|
|
3
|
+
export type Motion = Readonly<{
|
|
4
|
+
reduced: boolean;
|
|
5
|
+
squish: number;
|
|
6
|
+
fast: number;
|
|
7
|
+
normal: number;
|
|
8
|
+
slow: number;
|
|
9
|
+
springDuration: number;
|
|
10
|
+
bounce: number;
|
|
11
|
+
stretch: number;
|
|
12
|
+
distance: number;
|
|
13
|
+
stagger: number;
|
|
14
|
+
blur: number;
|
|
15
|
+
shake: number;
|
|
16
|
+
steps: number;
|
|
17
|
+
fuse: number;
|
|
18
|
+
pressDepth: number;
|
|
19
|
+
pressScale: number;
|
|
20
|
+
ease: string;
|
|
21
|
+
easeExit: string;
|
|
22
|
+
}>;
|
|
23
|
+
/** Read at an event boundary; no root-theme lookup, so nested tokens win. */
|
|
24
|
+
export declare function readMotion(element: Element): Motion;
|
|
25
|
+
/** Live motion tokens for a mounted ref, including nested theme and OS changes. */
|
|
26
|
+
export declare function useMotion(ref: RefObject<Element | null>): Motion;
|
|
27
|
+
/** Today's feel: the defaults that components' authored timings are written against. */
|
|
28
|
+
export declare const motionDefaults: Motion;
|
|
29
|
+
/**
|
|
30
|
+
* Scale one of a component's authored durations by the theme's tempo
|
|
31
|
+
* (`--stipe-motion-normal` against its 180ms default). Today's themes return
|
|
32
|
+
* the authored value unchanged; reduced motion returns 0 (nothing travels).
|
|
33
|
+
*/
|
|
34
|
+
export declare function motionTime(motion: Motion, authored: number): number;
|
|
35
|
+
/**
|
|
36
|
+
* Scale one of a component's authored spring bounces by the theme's bounce
|
|
37
|
+
* (`--stipe-motion-bounce` against its 0.3 default), so a lively control stays
|
|
38
|
+
* livelier than a calm one inside every theme. A 0 theme is critically damped.
|
|
39
|
+
*/
|
|
40
|
+
export declare function motionBounce(motion: Motion, authored: number): number;
|
|
41
|
+
/** Scale an authored spring settle time by `--stipe-motion-spring-duration`. */
|
|
42
|
+
export declare function motionSpringTime(motion: Motion, authored: number): number;
|
|
43
|
+
/** A CSS easing for a Web Animation, stepped when the theme asks for it. */
|
|
44
|
+
export declare function motionEasing(motion: Motion, ease: string): string;
|
|
45
|
+
/** Whether the element can run Web Animations (not in jsdom or old engines). */
|
|
46
|
+
export declare function canAnimate(element: Element): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* The live reduced-motion preference alone, for controls that only need to
|
|
49
|
+
* know whether to move (their timing comes from `readMotion` when they do).
|
|
50
|
+
*/
|
|
51
|
+
export declare function useReducedMotion(): boolean;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { useLayoutEffect, useState, useSyncExternalStore, } from "react";
|
|
2
|
+
const defaults = Object.freeze({
|
|
3
|
+
reduced: false,
|
|
4
|
+
squish: 90,
|
|
5
|
+
fast: 120,
|
|
6
|
+
normal: 180,
|
|
7
|
+
slow: 280,
|
|
8
|
+
springDuration: 320,
|
|
9
|
+
bounce: 0.3,
|
|
10
|
+
stretch: 0.28,
|
|
11
|
+
distance: 4,
|
|
12
|
+
stagger: 24,
|
|
13
|
+
blur: 0,
|
|
14
|
+
shake: 3,
|
|
15
|
+
steps: 0,
|
|
16
|
+
fuse: 1,
|
|
17
|
+
pressDepth: 0.5,
|
|
18
|
+
pressScale: 1,
|
|
19
|
+
ease: "cubic-bezier(0.2, 0, 0, 1)",
|
|
20
|
+
easeExit: "cubic-bezier(0.4, 0, 1, 1)",
|
|
21
|
+
});
|
|
22
|
+
const preference = "(prefers-reduced-motion: reduce)";
|
|
23
|
+
/** Read at an event boundary; no root-theme lookup, so nested tokens win. */
|
|
24
|
+
export function readMotion(element) {
|
|
25
|
+
const view = element.ownerDocument.defaultView;
|
|
26
|
+
if (!view)
|
|
27
|
+
return defaults;
|
|
28
|
+
const style = view.getComputedStyle(element);
|
|
29
|
+
const number = (name, fallback) => {
|
|
30
|
+
const value = style.getPropertyValue(name).trim();
|
|
31
|
+
const parsed = Number.parseFloat(value);
|
|
32
|
+
return Number.isFinite(parsed) ? Math.max(0, parsed) : fallback;
|
|
33
|
+
};
|
|
34
|
+
const time = (name, fallback) => {
|
|
35
|
+
const value = style.getPropertyValue(name).trim();
|
|
36
|
+
return (number(name, fallback) *
|
|
37
|
+
(value.endsWith("s") && !value.endsWith("ms") ? 1000 : 1));
|
|
38
|
+
};
|
|
39
|
+
const browser = view;
|
|
40
|
+
const reduced = browser.matchMedia?.(preference).matches ?? false;
|
|
41
|
+
const duration = (name, fallback) => reduced ? 120 : time(`--stipe-motion-${name}`, fallback);
|
|
42
|
+
const amount = (name, fallback) => reduced ? 0 : number(`--stipe-motion-${name}`, fallback);
|
|
43
|
+
return {
|
|
44
|
+
reduced,
|
|
45
|
+
squish: duration("squish", defaults.squish),
|
|
46
|
+
fast: duration("fast", defaults.fast),
|
|
47
|
+
normal: duration("normal", defaults.normal),
|
|
48
|
+
slow: duration("slow", defaults.slow),
|
|
49
|
+
springDuration: duration("spring-duration", defaults.springDuration),
|
|
50
|
+
bounce: Math.min(1, amount("bounce", defaults.bounce)),
|
|
51
|
+
stretch: amount("stretch", defaults.stretch),
|
|
52
|
+
distance: amount("distance", defaults.distance),
|
|
53
|
+
stagger: reduced ? 0 : time("--stipe-motion-stagger", defaults.stagger),
|
|
54
|
+
blur: amount("blur", defaults.blur),
|
|
55
|
+
shake: amount("shake", defaults.shake),
|
|
56
|
+
steps: Math.floor(amount("steps", defaults.steps)),
|
|
57
|
+
fuse: number("--stipe-motion-fuse", defaults.fuse),
|
|
58
|
+
pressDepth: reduced
|
|
59
|
+
? 0
|
|
60
|
+
: number("--stipe-press-depth", defaults.pressDepth),
|
|
61
|
+
pressScale: reduced
|
|
62
|
+
? 1
|
|
63
|
+
: number("--stipe-press-scale", defaults.pressScale),
|
|
64
|
+
ease: style.getPropertyValue("--stipe-motion-ease").trim() || defaults.ease,
|
|
65
|
+
easeExit: style.getPropertyValue("--stipe-motion-ease-exit").trim() ||
|
|
66
|
+
defaults.easeExit,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** Live motion tokens for a mounted ref, including nested theme and OS changes. */
|
|
70
|
+
export function useMotion(ref) {
|
|
71
|
+
const [motion, setMotion] = useState(() => ({
|
|
72
|
+
...defaults,
|
|
73
|
+
reduced: true,
|
|
74
|
+
}));
|
|
75
|
+
useLayoutEffect(() => {
|
|
76
|
+
const element = ref.current;
|
|
77
|
+
const view = element?.ownerDocument.defaultView;
|
|
78
|
+
if (!element || !view)
|
|
79
|
+
return;
|
|
80
|
+
const update = () => {
|
|
81
|
+
const next = readMotion(element);
|
|
82
|
+
setMotion((previous) => JSON.stringify(previous) === JSON.stringify(next) ? previous : next);
|
|
83
|
+
};
|
|
84
|
+
update();
|
|
85
|
+
const observer = new view.MutationObserver(update);
|
|
86
|
+
// Observe ancestors only: animation writes to descendants must not trigger reads.
|
|
87
|
+
for (let parent = element; parent; parent = parent.parentElement) {
|
|
88
|
+
observer.observe(parent, {
|
|
89
|
+
attributes: true,
|
|
90
|
+
attributeFilter: ["data-theme", "class", "style"],
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
const browser = view;
|
|
94
|
+
const media = browser.matchMedia?.(preference);
|
|
95
|
+
media?.addEventListener("change", update);
|
|
96
|
+
return () => {
|
|
97
|
+
observer.disconnect();
|
|
98
|
+
media?.removeEventListener("change", update);
|
|
99
|
+
};
|
|
100
|
+
}, [ref]);
|
|
101
|
+
return motion;
|
|
102
|
+
}
|
|
103
|
+
/** Today's feel: the defaults that components' authored timings are written against. */
|
|
104
|
+
export const motionDefaults = defaults;
|
|
105
|
+
/**
|
|
106
|
+
* Scale one of a component's authored durations by the theme's tempo
|
|
107
|
+
* (`--stipe-motion-normal` against its 180ms default). Today's themes return
|
|
108
|
+
* the authored value unchanged; reduced motion returns 0 (nothing travels).
|
|
109
|
+
*/
|
|
110
|
+
export function motionTime(motion, authored) {
|
|
111
|
+
if (motion.reduced)
|
|
112
|
+
return 0;
|
|
113
|
+
return Math.round((authored * motion.normal) / defaults.normal);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Scale one of a component's authored spring bounces by the theme's bounce
|
|
117
|
+
* (`--stipe-motion-bounce` against its 0.3 default), so a lively control stays
|
|
118
|
+
* livelier than a calm one inside every theme. A 0 theme is critically damped.
|
|
119
|
+
*/
|
|
120
|
+
export function motionBounce(motion, authored) {
|
|
121
|
+
if (motion.reduced)
|
|
122
|
+
return 0;
|
|
123
|
+
const scaled = (authored * motion.bounce) / defaults.bounce;
|
|
124
|
+
return Math.min(0.9, Math.max(0, scaled));
|
|
125
|
+
}
|
|
126
|
+
/** Scale an authored spring settle time by `--stipe-motion-spring-duration`. */
|
|
127
|
+
export function motionSpringTime(motion, authored) {
|
|
128
|
+
if (motion.reduced)
|
|
129
|
+
return 0;
|
|
130
|
+
return Math.round((authored * motion.springDuration) / defaults.springDuration);
|
|
131
|
+
}
|
|
132
|
+
/** A CSS easing for a Web Animation, stepped when the theme asks for it. */
|
|
133
|
+
export function motionEasing(motion, ease) {
|
|
134
|
+
return motion.steps > 0 ? `steps(${String(motion.steps)}, end)` : ease;
|
|
135
|
+
}
|
|
136
|
+
/** Whether the element can run Web Animations (not in jsdom or old engines). */
|
|
137
|
+
export function canAnimate(element) {
|
|
138
|
+
return "animate" in element;
|
|
139
|
+
}
|
|
140
|
+
const globalWindow = globalThis;
|
|
141
|
+
function prefersReducedMotion() {
|
|
142
|
+
return globalWindow.matchMedia?.(preference).matches ?? false;
|
|
143
|
+
}
|
|
144
|
+
function subscribeReducedMotion(update) {
|
|
145
|
+
const media = globalWindow.matchMedia?.(preference);
|
|
146
|
+
media?.addEventListener("change", update);
|
|
147
|
+
return () => {
|
|
148
|
+
media?.removeEventListener("change", update);
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/** Server renders assume reduced motion, so hydration never starts mid-move. */
|
|
152
|
+
function serverReducedMotion() {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The live reduced-motion preference alone, for controls that only need to
|
|
157
|
+
* know whether to move (their timing comes from `readMotion` when they do).
|
|
158
|
+
*/
|
|
159
|
+
export function useReducedMotion() {
|
|
160
|
+
return useSyncExternalStore(subscribeReducedMotion, prefersReducedMotion, serverReducedMotion);
|
|
161
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
/** The attribute that names one keyed child of a list with list motion. */
|
|
3
|
+
export declare const reorderKeyAttribute = "data-reorder-key";
|
|
4
|
+
/**
|
|
5
|
+
* Motion for a keyed list. Rows that arrive fade in over the theme's travel
|
|
6
|
+
* (staggered by `--stipe-motion-stagger`) once the list has unrolled to make
|
|
7
|
+
* room. A row that leaves fades where it stood first; then the rest close
|
|
8
|
+
* ranks, gliding to their places (FLIP on the Web Animations API) as the list
|
|
9
|
+
* eases to its new height. Everything reads the theme's motion tokens;
|
|
10
|
+
* reduced motion keeps only short fades and nothing travels. Children opt in
|
|
11
|
+
* with `data-reorder-key`, and the first render is still.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useListMotion(container: RefObject<HTMLElement | null>, order: readonly string[]): void;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { useLayoutEffect, useRef } from "react";
|
|
2
|
+
import { canAnimate, motionEasing, readMotion } from "./motion.js";
|
|
3
|
+
/** The attribute that names one keyed child of a list with list motion. */
|
|
4
|
+
export const reorderKeyAttribute = "data-reorder-key";
|
|
5
|
+
function rowIn(container, element) {
|
|
6
|
+
const outer = container.getBoundingClientRect();
|
|
7
|
+
const inner = element.getBoundingClientRect();
|
|
8
|
+
// Container-relative, so scrolling between renders never reads as a move.
|
|
9
|
+
return {
|
|
10
|
+
element,
|
|
11
|
+
top: inner.top - outer.top + container.scrollTop,
|
|
12
|
+
left: inner.left - outer.left + container.scrollLeft,
|
|
13
|
+
width: inner.width,
|
|
14
|
+
height: inner.height,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Rows that arrive fade in over the theme's travel, a sibling at a time. */
|
|
18
|
+
function enter(rows, motion, after) {
|
|
19
|
+
rows.forEach((element, index) => {
|
|
20
|
+
element.animate(motion.reduced
|
|
21
|
+
? [{ opacity: 0 }, { opacity: 1 }]
|
|
22
|
+
: [
|
|
23
|
+
{
|
|
24
|
+
opacity: 0,
|
|
25
|
+
transform: `translateY(${String(motion.distance)}px)`,
|
|
26
|
+
},
|
|
27
|
+
{ opacity: 1, transform: "none" },
|
|
28
|
+
], {
|
|
29
|
+
duration: motion.normal,
|
|
30
|
+
delay: after + index * motion.stagger,
|
|
31
|
+
easing: motionEasing(motion, motion.ease),
|
|
32
|
+
fill: "backwards",
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A row that leaves is gone from the DOM already; a quiet copy of its last
|
|
38
|
+
* look fades where it stood while the rows below glide up into its room.
|
|
39
|
+
*/
|
|
40
|
+
function leave(container, row, motion) {
|
|
41
|
+
const ghost = row.element.cloneNode(true);
|
|
42
|
+
if (!(ghost instanceof HTMLElement))
|
|
43
|
+
return;
|
|
44
|
+
ghost.removeAttribute(reorderKeyAttribute);
|
|
45
|
+
ghost.removeAttribute("id");
|
|
46
|
+
ghost.setAttribute("aria-hidden", "true");
|
|
47
|
+
ghost.setAttribute("inert", "");
|
|
48
|
+
Object.assign(ghost.style, {
|
|
49
|
+
position: "absolute",
|
|
50
|
+
top: `${String(row.top - container.clientTop)}px`,
|
|
51
|
+
left: `${String(row.left - container.clientLeft)}px`,
|
|
52
|
+
width: `${String(row.width)}px`,
|
|
53
|
+
height: `${String(row.height)}px`,
|
|
54
|
+
margin: "0",
|
|
55
|
+
pointerEvents: "none",
|
|
56
|
+
});
|
|
57
|
+
const positioned = getComputedStyle(container).position !== "static";
|
|
58
|
+
if (!positioned)
|
|
59
|
+
container.style.position = "relative";
|
|
60
|
+
container.append(ghost);
|
|
61
|
+
const exit = ghost.animate(motion.reduced
|
|
62
|
+
? [{ opacity: 1 }, { opacity: 0 }]
|
|
63
|
+
: [
|
|
64
|
+
{ opacity: 1, transform: "none" },
|
|
65
|
+
{
|
|
66
|
+
opacity: 0,
|
|
67
|
+
transform: `translateY(${String(-motion.distance)}px)`,
|
|
68
|
+
},
|
|
69
|
+
], {
|
|
70
|
+
duration: motion.fast,
|
|
71
|
+
easing: motionEasing(motion, motion.easeExit),
|
|
72
|
+
fill: "forwards",
|
|
73
|
+
});
|
|
74
|
+
const done = () => {
|
|
75
|
+
ghost.remove();
|
|
76
|
+
if (!positioned && container.querySelector(":scope > [inert]") === null)
|
|
77
|
+
container.style.removeProperty("position");
|
|
78
|
+
};
|
|
79
|
+
exit.addEventListener("finish", done);
|
|
80
|
+
exit.addEventListener("cancel", done);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The list eases to its new height with the rows, so whatever sits below it
|
|
84
|
+
* moves along instead of jumping; rows outside the moving edge are clipped.
|
|
85
|
+
*/
|
|
86
|
+
function resize(container, from, to, timing) {
|
|
87
|
+
const clipped = container.style.overflow;
|
|
88
|
+
container.style.overflow = "clip";
|
|
89
|
+
const animation = container.animate([{ height: `${String(from)}px` }, { height: `${String(to)}px` }], timing);
|
|
90
|
+
const done = () => {
|
|
91
|
+
container.style.overflow = clipped;
|
|
92
|
+
};
|
|
93
|
+
animation.addEventListener("finish", done);
|
|
94
|
+
animation.addEventListener("cancel", done);
|
|
95
|
+
return animation;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Motion for a keyed list. Rows that arrive fade in over the theme's travel
|
|
99
|
+
* (staggered by `--stipe-motion-stagger`) once the list has unrolled to make
|
|
100
|
+
* room. A row that leaves fades where it stood first; then the rest close
|
|
101
|
+
* ranks, gliding to their places (FLIP on the Web Animations API) as the list
|
|
102
|
+
* eases to its new height. Everything reads the theme's motion tokens;
|
|
103
|
+
* reduced motion keeps only short fades and nothing travels. Children opt in
|
|
104
|
+
* with `data-reorder-key`, and the first render is still.
|
|
105
|
+
*/
|
|
106
|
+
export function useListMotion(container, order) {
|
|
107
|
+
const previous = useRef(null);
|
|
108
|
+
const height = useRef(0);
|
|
109
|
+
const resizing = useRef(null);
|
|
110
|
+
const orderKey = order.join("\u0000");
|
|
111
|
+
useLayoutEffect(() => {
|
|
112
|
+
const root = container.current;
|
|
113
|
+
if (root === null) {
|
|
114
|
+
// A list that unmounts starts still when it comes back.
|
|
115
|
+
previous.current = null;
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const before = previous.current;
|
|
119
|
+
const changed = before?.order !== orderKey;
|
|
120
|
+
// Measure the list's own height, not a resize still in flight.
|
|
121
|
+
const heightBefore = resizing.current
|
|
122
|
+
? root.getBoundingClientRect().height
|
|
123
|
+
: height.current;
|
|
124
|
+
if (changed) {
|
|
125
|
+
resizing.current?.cancel();
|
|
126
|
+
resizing.current = null;
|
|
127
|
+
}
|
|
128
|
+
const heightAfter = changed
|
|
129
|
+
? root.getBoundingClientRect().height
|
|
130
|
+
: height.current;
|
|
131
|
+
height.current = heightAfter;
|
|
132
|
+
const next = new Map();
|
|
133
|
+
for (const element of root.querySelectorAll(`:scope [${reorderKeyAttribute}]`)) {
|
|
134
|
+
const key = element.getAttribute(reorderKeyAttribute);
|
|
135
|
+
if (key === null)
|
|
136
|
+
continue;
|
|
137
|
+
const was = before?.rows.get(key);
|
|
138
|
+
// Unchanged rows already have their target positions. Measuring them
|
|
139
|
+
// during our own animation would replace that target with a halfway pose.
|
|
140
|
+
next.set(key, !changed && was?.element === element ? was : rowIn(root, element));
|
|
141
|
+
}
|
|
142
|
+
const keys = new Set(order);
|
|
143
|
+
previous.current = { order: orderKey, keys, rows: next };
|
|
144
|
+
// Virtual lists mount and unmount rows while scrolling. Refresh their
|
|
145
|
+
// baseline every commit, but animate only a change to the logical list.
|
|
146
|
+
if (before === null || !changed || !canAnimate(root))
|
|
147
|
+
return;
|
|
148
|
+
const motion = readMotion(root);
|
|
149
|
+
const leaving = [...before.rows].filter(([key, row]) => !keys.has(key) && !row.element.isConnected);
|
|
150
|
+
// Ranks close once the leaving rows have faded, never through them.
|
|
151
|
+
const settle = {
|
|
152
|
+
duration: motion.slow,
|
|
153
|
+
delay: leaving.length > 0 ? motion.fast : 0,
|
|
154
|
+
easing: motionEasing(motion, motion.ease),
|
|
155
|
+
fill: "backwards",
|
|
156
|
+
};
|
|
157
|
+
const arriving = [];
|
|
158
|
+
const moved = [];
|
|
159
|
+
for (const [key, row] of next) {
|
|
160
|
+
const was = before.rows.get(key);
|
|
161
|
+
if (was === undefined) {
|
|
162
|
+
if (!before.keys.has(key))
|
|
163
|
+
arriving.push(row.element);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const dx = was.left - row.left;
|
|
167
|
+
const dy = was.top - row.top;
|
|
168
|
+
if (dx === 0 && dy === 0)
|
|
169
|
+
continue;
|
|
170
|
+
moved.push(row.element);
|
|
171
|
+
if (motion.reduced || motion.slow <= 0)
|
|
172
|
+
continue;
|
|
173
|
+
row.element.animate([
|
|
174
|
+
{ transform: `translate(${String(dx)}px, ${String(dy)}px)` },
|
|
175
|
+
{ transform: "none" },
|
|
176
|
+
], settle);
|
|
177
|
+
}
|
|
178
|
+
if (motion.reduced) {
|
|
179
|
+
// Nothing travels: rows that changed place settle in with a short fade
|
|
180
|
+
// instead of a fading copy crossing them.
|
|
181
|
+
for (const element of moved)
|
|
182
|
+
element.animate([{ opacity: 0.3 }, { opacity: 1 }], {
|
|
183
|
+
duration: motion.fast,
|
|
184
|
+
easing: motion.ease,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
else
|
|
188
|
+
for (const [, row] of leaving)
|
|
189
|
+
leave(root, row, motion);
|
|
190
|
+
// New rows fade in once the rows around them have made room.
|
|
191
|
+
enter(arriving, motion, moved.length > 0 && !motion.reduced ? motion.fast : 0);
|
|
192
|
+
if (!motion.reduced && Math.abs(heightBefore - heightAfter) > 0.5) {
|
|
193
|
+
const animation = resize(root, heightBefore, heightAfter, settle);
|
|
194
|
+
resizing.current = animation;
|
|
195
|
+
animation.addEventListener("finish", () => {
|
|
196
|
+
if (resizing.current === animation)
|
|
197
|
+
resizing.current = null;
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A stable 32-bit FNV-1a hash: the same seed always lands on the same value,
|
|
3
|
+
* and short, similar seeds spread apart. Used to pick a deterministic tone,
|
|
4
|
+
* color, or pattern from an identity (a name, an Agent id) without state.
|
|
5
|
+
*/
|
|
6
|
+
export declare function seedHash(seed: string): number;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A stable 32-bit FNV-1a hash: the same seed always lands on the same value,
|
|
3
|
+
* and short, similar seeds spread apart. Used to pick a deterministic tone,
|
|
4
|
+
* color, or pattern from an identity (a name, an Agent id) without state.
|
|
5
|
+
*/
|
|
6
|
+
export function seedHash(seed) {
|
|
7
|
+
let hash = 0x811c9dc5;
|
|
8
|
+
for (const unit of seed) {
|
|
9
|
+
hash ^= unit.codePointAt(0) ?? 0;
|
|
10
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
11
|
+
}
|
|
12
|
+
return hash;
|
|
13
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Highlights Markdown fences with the shared chat and document language set. */
|
|
2
|
+
export declare const highlightMarkdownCode: import("@tanstack/highlight/markdown").TanStackMarkdownHighlighter;
|
|
3
|
+
/** Converts source code to escaped token spans for a code display. */
|
|
4
|
+
export declare function highlightToHtml(code: string, lang?: string): string;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createHighlighter } from "@tanstack/highlight/core";
|
|
2
|
+
import { css } from "@tanstack/highlight/languages/css";
|
|
3
|
+
import { dockerfile } from "@tanstack/highlight/languages/dockerfile";
|
|
4
|
+
import { html } from "@tanstack/highlight/languages/html";
|
|
5
|
+
import { js } from "@tanstack/highlight/languages/js";
|
|
6
|
+
import { json } from "@tanstack/highlight/languages/json";
|
|
7
|
+
import { jsx } from "@tanstack/highlight/languages/jsx";
|
|
8
|
+
import { markdown } from "@tanstack/highlight/languages/markdown";
|
|
9
|
+
import { plaintext } from "@tanstack/highlight/languages/plaintext";
|
|
10
|
+
import { python } from "@tanstack/highlight/languages/python";
|
|
11
|
+
import { shell } from "@tanstack/highlight/languages/shell";
|
|
12
|
+
import { sql } from "@tanstack/highlight/languages/sql";
|
|
13
|
+
import { ts } from "@tanstack/highlight/languages/ts";
|
|
14
|
+
import { tsx } from "@tanstack/highlight/languages/tsx";
|
|
15
|
+
import { yaml } from "@tanstack/highlight/languages/yaml";
|
|
16
|
+
import { createTanStackMarkdownHighlighter } from "@tanstack/highlight/markdown";
|
|
17
|
+
const highlighter = createHighlighter({
|
|
18
|
+
fallbackLanguage: "plaintext",
|
|
19
|
+
languages: [
|
|
20
|
+
css,
|
|
21
|
+
dockerfile,
|
|
22
|
+
html,
|
|
23
|
+
js,
|
|
24
|
+
json,
|
|
25
|
+
jsx,
|
|
26
|
+
markdown,
|
|
27
|
+
plaintext,
|
|
28
|
+
python,
|
|
29
|
+
shell,
|
|
30
|
+
sql,
|
|
31
|
+
ts,
|
|
32
|
+
tsx,
|
|
33
|
+
yaml,
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
/** Highlights Markdown fences with the shared chat and document language set. */
|
|
37
|
+
export const highlightMarkdownCode = createTanStackMarkdownHighlighter(highlighter);
|
|
38
|
+
/** Converts source code to escaped token spans for a code display. */
|
|
39
|
+
export function highlightToHtml(code, lang) {
|
|
40
|
+
return highlighter.highlightToHtml(code, lang ? { lang } : {});
|
|
41
|
+
}
|