@teamofsilicons/silicon-ui 0.0.0-stage → 0.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/LICENSE +22 -0
- package/README.md +81 -2
- package/check.mjs +236 -0
- package/components/accordion/accordion.d.ts +13 -0
- package/components/accordion/accordion.js +35 -0
- package/components/accordion/accordion.module.css +15 -0
- package/components/action-button/action-button.d.ts +11 -0
- package/components/action-button/action-button.js +57 -0
- package/components/action-button/action-button.module.css +15 -0
- package/components/activity-heatmap/activity-heatmap.d.ts +37 -0
- package/components/activity-heatmap/activity-heatmap.js +303 -0
- package/components/activity-heatmap/activity-heatmap.module.css +83 -0
- package/components/alert/alert.d.ts +13 -0
- package/components/alert/alert.js +79 -0
- package/components/alert/alert.module.css +15 -0
- package/components/animated-counter/animated-counter.d.ts +13 -0
- package/components/animated-counter/animated-counter.js +73 -0
- package/components/animated-counter/animated-counter.module.css +12 -0
- package/components/announcement-bar/announcement-bar.d.ts +53 -0
- package/components/announcement-bar/announcement-bar.js +187 -0
- package/components/announcement-bar/announcement-bar.module.css +60 -0
- package/components/avatar/avatar.d.ts +8 -0
- package/components/avatar/avatar.js +18 -0
- package/components/avatar/avatar.module.css +60 -0
- package/components/avatar-group/avatar-group.d.ts +13 -0
- package/components/avatar-group/avatar-group.js +24 -0
- package/components/avatar-group/avatar-group.module.css +27 -0
- package/components/badge/badge.d.ts +10 -0
- package/components/badge/badge.js +66 -0
- package/components/badge/badge.module.css +52 -0
- package/components/bar-chart/bar-chart.d.ts +32 -0
- package/components/bar-chart/bar-chart.js +327 -0
- package/components/bar-chart/bar-chart.module.css +49 -0
- package/components/billing-toggle/billing-toggle.d.ts +35 -0
- package/components/billing-toggle/billing-toggle.js +83 -0
- package/components/billing-toggle/billing-toggle.module.css +139 -0
- package/components/bottom-sheet/bottom-sheet.d.ts +27 -0
- package/components/bottom-sheet/bottom-sheet.js +386 -0
- package/components/bottom-sheet/bottom-sheet.module.css +69 -0
- package/components/breadcrumb/breadcrumb.d.ts +13 -0
- package/components/breadcrumb/breadcrumb.js +19 -0
- package/components/breadcrumb/breadcrumb.module.css +12 -0
- package/components/brush-chart/brush-chart.d.ts +45 -0
- package/components/brush-chart/brush-chart.js +426 -0
- package/components/brush-chart/brush-chart.module.css +69 -0
- package/components/button/button.d.ts +10 -0
- package/components/button/button.js +97 -0
- package/components/button/button.module.css +39 -0
- package/components/button-group/button-group.d.ts +59 -0
- package/components/button-group/button-group.js +280 -0
- package/components/button-group/button-group.module.css +87 -0
- package/components/button-link/button-link.d.ts +24 -0
- package/components/button-link/button-link.js +11 -0
- package/components/button-link/button-link.module.css +7 -0
- package/components/calendar/calendar.d.ts +22 -0
- package/components/calendar/calendar.js +253 -0
- package/components/calendar/calendar.module.css +51 -0
- package/components/card/card.d.ts +19 -0
- package/components/card/card.js +108 -0
- package/components/card/card.module.css +51 -0
- package/components/card-stack/card-stack.d.ts +34 -0
- package/components/card-stack/card-stack.js +291 -0
- package/components/card-stack/card-stack.module.css +63 -0
- package/components/carousel/carousel.d.ts +28 -0
- package/components/carousel/carousel.js +332 -0
- package/components/carousel/carousel.module.css +42 -0
- package/components/chat-thread/chat-thread.d.ts +135 -0
- package/components/chat-thread/chat-thread.js +406 -0
- package/components/chat-thread/chat-thread.module.css +242 -0
- package/components/checkbox/checkbox.d.ts +7 -0
- package/components/checkbox/checkbox.js +23 -0
- package/components/checkbox/checkbox.module.css +15 -0
- package/components/chip-group/chip-group.d.ts +24 -0
- package/components/chip-group/chip-group.js +196 -0
- package/components/chip-group/chip-group.module.css +38 -0
- package/components/code-block/code-block.d.ts +11 -0
- package/components/code-block/code-block.js +133 -0
- package/components/code-block/code-block.module.css +43 -0
- package/components/color-picker/color-picker.d.ts +40 -0
- package/components/color-picker/color-picker.js +449 -0
- package/components/color-picker/color-picker.module.css +111 -0
- package/components/combobox/combobox.d.ts +19 -0
- package/components/combobox/combobox.js +167 -0
- package/components/combobox/combobox.module.css +28 -0
- package/components/command-palette/command-palette.d.ts +20 -0
- package/components/command-palette/command-palette.js +151 -0
- package/components/command-palette/command-palette.module.css +94 -0
- package/components/comment-thread/comment-thread.d.ts +120 -0
- package/components/comment-thread/comment-thread.js +343 -0
- package/components/comment-thread/comment-thread.module.css +195 -0
- package/components/confirm-morph/confirm-morph.d.ts +65 -0
- package/components/confirm-morph/confirm-morph.js +355 -0
- package/components/confirm-morph/confirm-morph.module.css +146 -0
- package/components/context-menu/context-menu.d.ts +18 -0
- package/components/context-menu/context-menu.js +148 -0
- package/components/context-menu/context-menu.module.css +17 -0
- package/components/copy-button/copy-button.d.ts +10 -0
- package/components/copy-button/copy-button.js +69 -0
- package/components/copy-button/copy-button.module.css +21 -0
- package/components/countdown/countdown.d.ts +31 -0
- package/components/countdown/countdown.js +177 -0
- package/components/countdown/countdown.module.css +49 -0
- package/components/date-picker/date-picker.d.ts +17 -0
- package/components/date-picker/date-picker.js +100 -0
- package/components/date-picker/date-picker.module.css +34 -0
- package/components/date-range-picker/date-range-picker.d.ts +44 -0
- package/components/date-range-picker/date-range-picker.js +534 -0
- package/components/date-range-picker/date-range-picker.module.css +214 -0
- package/components/dialog/dialog.d.ts +11 -0
- package/components/dialog/dialog.js +52 -0
- package/components/dialog/dialog.module.css +36 -0
- package/components/donut-chart/donut-chart.d.ts +46 -0
- package/components/donut-chart/donut-chart.js +382 -0
- package/components/donut-chart/donut-chart.module.css +48 -0
- package/components/drawer/drawer.d.ts +20 -0
- package/components/drawer/drawer.js +111 -0
- package/components/drawer/drawer.module.css +97 -0
- package/components/dropdown-menu/dropdown-menu.d.ts +16 -0
- package/components/dropdown-menu/dropdown-menu.js +39 -0
- package/components/dropdown-menu/dropdown-menu.module.css +38 -0
- package/components/elastic-slider/elastic-slider.d.ts +39 -0
- package/components/elastic-slider/elastic-slider.js +261 -0
- package/components/elastic-slider/elastic-slider.module.css +40 -0
- package/components/empty-state/empty-state.d.ts +12 -0
- package/components/empty-state/empty-state.js +69 -0
- package/components/empty-state/empty-state.module.css +13 -0
- package/components/expandable-card/expandable-card.d.ts +13 -0
- package/components/expandable-card/expandable-card.js +89 -0
- package/components/expandable-card/expandable-card.module.css +22 -0
- package/components/expanding-button-group/expanding-button-group.d.ts +41 -0
- package/components/expanding-button-group/expanding-button-group.js +258 -0
- package/components/expanding-button-group/expanding-button-group.module.css +44 -0
- package/components/expanding-search/expanding-search.d.ts +38 -0
- package/components/expanding-search/expanding-search.js +242 -0
- package/components/expanding-search/expanding-search.module.css +52 -0
- package/components/file-dropzone/file-dropzone.d.ts +44 -0
- package/components/file-dropzone/file-dropzone.js +379 -0
- package/components/file-dropzone/file-dropzone.module.css +115 -0
- package/components/file-upload/file-upload.d.ts +22 -0
- package/components/file-upload/file-upload.js +192 -0
- package/components/file-upload/file-upload.module.css +49 -0
- package/components/filter-toolbar/filter-toolbar.d.ts +48 -0
- package/components/filter-toolbar/filter-toolbar.js +446 -0
- package/components/filter-toolbar/filter-toolbar.module.css +70 -0
- package/components/floating-button-group/floating-button-group.d.ts +51 -0
- package/components/floating-button-group/floating-button-group.js +215 -0
- package/components/floating-button-group/floating-button-group.module.css +74 -0
- package/components/gauge/gauge.d.ts +18 -0
- package/components/gauge/gauge.js +101 -0
- package/components/gauge/gauge.module.css +22 -0
- package/components/hold-to-confirm/hold-to-confirm.d.ts +25 -0
- package/components/hold-to-confirm/hold-to-confirm.js +165 -0
- package/components/hold-to-confirm/hold-to-confirm.module.css +20 -0
- package/components/hover-card/hover-card.d.ts +38 -0
- package/components/hover-card/hover-card.js +145 -0
- package/components/hover-card/hover-card.module.css +20 -0
- package/components/image-compare/image-compare.d.ts +27 -0
- package/components/image-compare/image-compare.js +267 -0
- package/components/image-compare/image-compare.module.css +25 -0
- package/components/in-view-title/in-view-title.d.ts +17 -0
- package/components/in-view-title/in-view-title.js +70 -0
- package/components/in-view-title/in-view-title.module.css +13 -0
- package/components/inline-edit/inline-edit.d.ts +27 -0
- package/components/inline-edit/inline-edit.js +315 -0
- package/components/inline-edit/inline-edit.module.css +73 -0
- package/components/input/input.d.ts +7 -0
- package/components/input/input.js +60 -0
- package/components/input/input.module.css +22 -0
- package/components/json-viewer/json-viewer.d.ts +48 -0
- package/components/json-viewer/json-viewer.js +463 -0
- package/components/json-viewer/json-viewer.module.css +92 -0
- package/components/line-chart/line-chart.d.ts +58 -0
- package/components/line-chart/line-chart.js +383 -0
- package/components/line-chart/line-chart.module.css +60 -0
- package/components/mention-input/mention-input.d.ts +72 -0
- package/components/mention-input/mention-input.js +417 -0
- package/components/mention-input/mention-input.module.css +134 -0
- package/components/metric-card/metric-card.d.ts +8 -0
- package/components/metric-card/metric-card.js +44 -0
- package/components/metric-card/metric-card.module.css +18 -0
- package/components/money-input/money-input.d.ts +48 -0
- package/components/money-input/money-input.js +503 -0
- package/components/money-input/money-input.module.css +77 -0
- package/components/morph-select/morph-select.d.ts +50 -0
- package/components/morph-select/morph-select.js +395 -0
- package/components/morph-select/morph-select.module.css +88 -0
- package/components/multi-select/multi-select.d.ts +18 -0
- package/components/multi-select/multi-select.js +105 -0
- package/components/multi-select/multi-select.module.css +37 -0
- package/components/notification-center/notification-center.d.ts +24 -0
- package/components/notification-center/notification-center.js +146 -0
- package/components/notification-center/notification-center.module.css +79 -0
- package/components/number-field/number-field.d.ts +41 -0
- package/components/number-field/number-field.js +455 -0
- package/components/number-field/number-field.module.css +71 -0
- package/components/otp-input/otp-input.d.ts +13 -0
- package/components/otp-input/otp-input.js +129 -0
- package/components/otp-input/otp-input.module.css +28 -0
- package/components/pagination/pagination.d.ts +7 -0
- package/components/pagination/pagination.js +60 -0
- package/components/pagination/pagination.module.css +16 -0
- package/components/password-field/password-field.d.ts +14 -0
- package/components/password-field/password-field.js +51 -0
- package/components/password-field/password-field.module.css +27 -0
- package/components/password-strength/password-strength.d.ts +107 -0
- package/components/password-strength/password-strength.js +161 -0
- package/components/password-strength/password-strength.module.css +57 -0
- package/components/phone-input/phone-input.d.ts +73 -0
- package/components/phone-input/phone-input.js +612 -0
- package/components/phone-input/phone-input.module.css +98 -0
- package/components/popover/popover.d.ts +6 -0
- package/components/popover/popover.js +19 -0
- package/components/popover/popover.module.css +32 -0
- package/components/progress/progress.d.ts +8 -0
- package/components/progress/progress.js +42 -0
- package/components/progress/progress.module.css +1 -0
- package/components/radio-cards/radio-cards.d.ts +35 -0
- package/components/radio-cards/radio-cards.js +110 -0
- package/components/radio-cards/radio-cards.module.css +84 -0
- package/components/radio-group/radio-group.d.ts +13 -0
- package/components/radio-group/radio-group.js +55 -0
- package/components/radio-group/radio-group.module.css +30 -0
- package/components/resizable-panels/resizable-panels.d.ts +37 -0
- package/components/resizable-panels/resizable-panels.js +338 -0
- package/components/resizable-panels/resizable-panels.module.css +40 -0
- package/components/rich-text-editor/rich-text-editor.d.ts +55 -0
- package/components/rich-text-editor/rich-text-editor.js +1733 -0
- package/components/rich-text-editor/rich-text-editor.module.css +201 -0
- package/components/ridgeline/ridgeline.d.ts +37 -0
- package/components/ridgeline/ridgeline.js +346 -0
- package/components/ridgeline/ridgeline.module.css +58 -0
- package/components/scroll-area/scroll-area.d.ts +40 -0
- package/components/scroll-area/scroll-area.js +153 -0
- package/components/scroll-area/scroll-area.module.css +79 -0
- package/components/search-field/search-field.d.ts +7 -0
- package/components/search-field/search-field.js +20 -0
- package/components/search-field/search-field.module.css +17 -0
- package/components/segmented-control/segmented-control.d.ts +16 -0
- package/components/segmented-control/segmented-control.js +56 -0
- package/components/segmented-control/segmented-control.module.css +15 -0
- package/components/select/select.d.ts +15 -0
- package/components/select/select.js +36 -0
- package/components/select/select.module.css +35 -0
- package/components/shortcut-recorder/shortcut-recorder.d.ts +108 -0
- package/components/shortcut-recorder/shortcut-recorder.js +380 -0
- package/components/shortcut-recorder/shortcut-recorder.module.css +85 -0
- package/components/signature-pad/signature-pad.d.ts +72 -0
- package/components/signature-pad/signature-pad.js +450 -0
- package/components/signature-pad/signature-pad.module.css +84 -0
- package/components/skeleton/skeleton.d.ts +13 -0
- package/components/skeleton/skeleton.js +53 -0
- package/components/skeleton/skeleton.module.css +11 -0
- package/components/slider/slider.d.ts +45 -0
- package/components/slider/slider.js +347 -0
- package/components/slider/slider.module.css +45 -0
- package/components/slope-chart/slope-chart.d.ts +38 -0
- package/components/slope-chart/slope-chart.js +183 -0
- package/components/slope-chart/slope-chart.module.css +51 -0
- package/components/slot-text/slot-text.d.ts +26 -0
- package/components/slot-text/slot-text.js +119 -0
- package/components/slot-text/slot-text.module.css +19 -0
- package/components/sortable-data-table/sortable-data-table.d.ts +38 -0
- package/components/sortable-data-table/sortable-data-table.js +240 -0
- package/components/sortable-data-table/sortable-data-table.module.css +116 -0
- package/components/sparkline/sparkline.d.ts +19 -0
- package/components/sparkline/sparkline.js +239 -0
- package/components/sparkline/sparkline.module.css +26 -0
- package/components/split-button/split-button.d.ts +19 -0
- package/components/split-button/split-button.js +33 -0
- package/components/split-button/split-button.module.css +51 -0
- package/components/stepper/stepper.d.ts +36 -0
- package/components/stepper/stepper.js +108 -0
- package/components/stepper/stepper.module.css +74 -0
- package/components/streamgraph/streamgraph.d.ts +51 -0
- package/components/streamgraph/streamgraph.js +376 -0
- package/components/streamgraph/streamgraph.module.css +55 -0
- package/components/swipe-actions/swipe-actions.d.ts +35 -0
- package/components/swipe-actions/swipe-actions.js +330 -0
- package/components/swipe-actions/swipe-actions.module.css +64 -0
- package/components/switch/switch.d.ts +7 -0
- package/components/switch/switch.js +45 -0
- package/components/switch/switch.module.css +12 -0
- package/components/tabs/tabs.d.ts +8 -0
- package/components/tabs/tabs.js +138 -0
- package/components/tabs/tabs.module.css +27 -0
- package/components/tag-input/tag-input.d.ts +15 -0
- package/components/tag-input/tag-input.js +150 -0
- package/components/tag-input/tag-input.module.css +34 -0
- package/components/text-morph/text-morph.d.ts +13 -0
- package/components/text-morph/text-morph.js +69 -0
- package/components/text-morph/text-morph.module.css +8 -0
- package/components/text-reveal/text-reveal.d.ts +14 -0
- package/components/text-reveal/text-reveal.js +20 -0
- package/components/text-reveal/text-reveal.module.css +13 -0
- package/components/text-shimmer/text-shimmer.d.ts +18 -0
- package/components/text-shimmer/text-shimmer.js +90 -0
- package/components/text-shimmer/text-shimmer.module.css +9 -0
- package/components/textarea/textarea.d.ts +7 -0
- package/components/textarea/textarea.js +56 -0
- package/components/textarea/textarea.module.css +22 -0
- package/components/theme-switch/theme-switch.d.ts +11 -0
- package/components/theme-switch/theme-switch.js +37 -0
- package/components/theme-switch/theme-switch.module.css +31 -0
- package/components/time-picker/time-picker.d.ts +13 -0
- package/components/time-picker/time-picker.js +95 -0
- package/components/time-picker/time-picker.module.css +23 -0
- package/components/timeline/timeline.d.ts +47 -0
- package/components/timeline/timeline.js +171 -0
- package/components/timeline/timeline.module.css +51 -0
- package/components/toast/toast.d.ts +8 -0
- package/components/toast/toast.js +118 -0
- package/components/toast/toast.module.css +100 -0
- package/components/toast-stack/toast-stack.d.ts +57 -0
- package/components/toast-stack/toast-stack.js +399 -0
- package/components/toast-stack/toast-stack.module.css +61 -0
- package/components/tooltip/tooltip.d.ts +8 -0
- package/components/tooltip/tooltip.js +62 -0
- package/components/tooltip/tooltip.module.css +18 -0
- package/components/tree-view/tree-view.d.ts +17 -0
- package/components/tree-view/tree-view.js +147 -0
- package/components/tree-view/tree-view.module.css +22 -0
- package/components/treemap/treemap.d.ts +35 -0
- package/components/treemap/treemap.js +375 -0
- package/components/treemap/treemap.module.css +59 -0
- package/components/usage-meter/usage-meter.d.ts +24 -0
- package/components/usage-meter/usage-meter.js +296 -0
- package/components/usage-meter/usage-meter.module.css +61 -0
- package/components/user-menu/user-menu.d.ts +62 -0
- package/components/user-menu/user-menu.js +316 -0
- package/components/user-menu/user-menu.module.css +97 -0
- package/components/waffle-chart/waffle-chart.d.ts +39 -0
- package/components/waffle-chart/waffle-chart.js +244 -0
- package/components/waffle-chart/waffle-chart.module.css +52 -0
- package/components.json +1330 -0
- package/eslint.js +53 -0
- package/lib/escape.d.ts +19 -0
- package/lib/escape.js +50 -0
- package/lib/media.d.ts +353 -0
- package/lib/media.js +65 -0
- package/lib/menu-highlight.d.ts +28 -0
- package/lib/menu-highlight.js +43 -0
- package/lib/motion-tokens.d.ts +60 -0
- package/lib/motion-tokens.js +25 -0
- package/lib/return-focus.d.ts +9 -0
- package/lib/return-focus.js +53 -0
- package/lib/silicon-provider.d.ts +60 -0
- package/lib/silicon-provider.js +47 -0
- package/lib/use-copy-feedback.d.ts +8 -0
- package/lib/use-copy-feedback.js +36 -0
- package/lib/use-today.d.ts +2 -0
- package/lib/use-today.js +29 -0
- package/package.json +76 -4
- package/styles.css +218 -0
- package/styles.css.d.ts +1 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
|
|
4
|
+
import { ChevronDown, FileCode2 } from "lucide-react";
|
|
5
|
+
import { AnimatePresence, animate, motion, useMotionValue, useReducedMotion } from "motion/react";
|
|
6
|
+
import { motionTokens } from "../../lib/motion-tokens.js";
|
|
7
|
+
import { CopyButton } from "../copy-button/copy-button.js";
|
|
8
|
+
import styles from "./code-block.module.css";
|
|
9
|
+
const keywordPattern = /^(?:abstract|as|async|await|break|case|catch|class|const|continue|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|of|private|protected|public|readonly|return|set|static|switch|throw|try|type|typeof|var|void|while|with|yield|SELECT|FROM|WHERE|INSERT|UPDATE|DELETE)$/;
|
|
10
|
+
const literalPattern = /^(?:true|false|null|undefined|NaN|Infinity)$/;
|
|
11
|
+
const typePattern = /^(?:Array|Boolean|Date|Error|Map|Number|Promise|Record|Set|String|ReactNode|HTMLElement|HTMLButtonElement|Event|unknown|never|void|any|boolean|number|string|object)$/;
|
|
12
|
+
const tokenPattern = /\/\*[\s\S]*?\*\/|\/\/[^\n]*|<!--[\s\S]*?-->|`(?:\\.|[^`\\])*`|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\b\d+(?:\.\d+)?\b|\b[A-Za-z_$][\w$-]*\b|[{}[\]();,.<>:=+*/!?|&-]/g;
|
|
13
|
+
function normaliseLanguage(language) {
|
|
14
|
+
return language.toLowerCase().replace(/^\./, "");
|
|
15
|
+
}
|
|
16
|
+
function tokenKind(value, source, index, language) {
|
|
17
|
+
if (value.startsWith("//") || value.startsWith("/*") || value.startsWith("<!--"))
|
|
18
|
+
return "comment";
|
|
19
|
+
if (value.startsWith("\"") || value.startsWith("'") || value.startsWith("`")) {
|
|
20
|
+
return language === "json" && /^\s*:/.test(source.slice(index + value.length)) ? "property" : "string";
|
|
21
|
+
}
|
|
22
|
+
if (/^\d/.test(value))
|
|
23
|
+
return "number";
|
|
24
|
+
if (keywordPattern.test(value) || literalPattern.test(value))
|
|
25
|
+
return "keyword";
|
|
26
|
+
if (typePattern.test(value))
|
|
27
|
+
return "type";
|
|
28
|
+
if (/^[{}[\]();,.<>:=+*/!?|&-]$/.test(value))
|
|
29
|
+
return "punctuation";
|
|
30
|
+
const before = source.slice(0, index);
|
|
31
|
+
const after = source.slice(index + value.length);
|
|
32
|
+
if ((language === "tsx" || language === "jsx" || language === "html" || language === "vue") && /<\/?$/.test(before))
|
|
33
|
+
return "tag";
|
|
34
|
+
if (/^\s*\(/.test(after) && language !== "json")
|
|
35
|
+
return "function";
|
|
36
|
+
if ((language === "css" || language === "tsx" || language === "jsx") && /^\s*[:=]/.test(after))
|
|
37
|
+
return "property";
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
function highlight(code, language) {
|
|
41
|
+
const parts = [];
|
|
42
|
+
let cursor = 0;
|
|
43
|
+
for (const match of code.matchAll(tokenPattern)) {
|
|
44
|
+
const value = match[0];
|
|
45
|
+
const index = match.index ?? 0;
|
|
46
|
+
if (cursor < index)
|
|
47
|
+
parts.push(code.slice(cursor, index));
|
|
48
|
+
const kind = tokenKind(value, code, index, language);
|
|
49
|
+
parts.push(kind ? _jsx("span", { className: styles[kind], children: value }, `${index}-${value}`) : _jsx(Fragment, { children: value }, `${index}-${value}`));
|
|
50
|
+
cursor = index + value.length;
|
|
51
|
+
}
|
|
52
|
+
if (cursor < code.length)
|
|
53
|
+
parts.push(code.slice(cursor));
|
|
54
|
+
return parts;
|
|
55
|
+
}
|
|
56
|
+
const textEnter = { duration: motionTokens.duration.standard, ease: [...motionTokens.ease.enter] };
|
|
57
|
+
const textExit = { duration: motionTokens.duration.instant, ease: [...motionTokens.ease.standard] };
|
|
58
|
+
/** Text that changes in place: the new words rise in with a soft blur while the old ones leave upward, faster. */
|
|
59
|
+
function SwapText({ value, reduced }) {
|
|
60
|
+
return _jsx(AnimatePresence, { initial: false, children: _jsx(motion.span, { className: styles.swapText, initial: reduced ? false : { opacity: 0, y: "0.3em", filter: `blur(${motionTokens.blur.soft}px)` }, animate: { opacity: 1, y: 0, filter: "blur(0px)" }, exit: reduced ? { opacity: 0, transition: { duration: 0 } } : { opacity: 0, y: "-0.3em", filter: `blur(${motionTokens.blur.subtle}px)`, transition: textExit }, transition: reduced ? { duration: 0 } : textEnter, children: value }, value) });
|
|
61
|
+
}
|
|
62
|
+
/** A new file name swaps in while its box follows the new width on a spring, then returns to auto so it can still truncate. */
|
|
63
|
+
function FileName({ name, reduced }) {
|
|
64
|
+
const sizer = useRef(null);
|
|
65
|
+
const rest = useRef(0);
|
|
66
|
+
const width = useMotionValue("auto");
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const node = sizer.current;
|
|
69
|
+
if (!node)
|
|
70
|
+
return;
|
|
71
|
+
const observer = new ResizeObserver(() => { rest.current = node.offsetWidth; });
|
|
72
|
+
observer.observe(node);
|
|
73
|
+
return () => observer.disconnect();
|
|
74
|
+
}, []);
|
|
75
|
+
useLayoutEffect(() => {
|
|
76
|
+
const moving = width.get(), to = sizer.current?.offsetWidth ?? 0;
|
|
77
|
+
const from = typeof moving === "number" ? moving : rest.current;
|
|
78
|
+
rest.current = to;
|
|
79
|
+
if (reduced || !from || !to || Math.abs(from - to) < 1) {
|
|
80
|
+
width.jump("auto");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
width.jump(from);
|
|
84
|
+
const controls = animate(width, to, { ...motionTokens.spring.morph, onComplete: () => width.jump("auto") });
|
|
85
|
+
return () => controls.stop();
|
|
86
|
+
}, [name, reduced, width]);
|
|
87
|
+
return _jsxs(motion.span, { className: `${styles.swap} ${styles.filename}`, style: { width }, children: [_jsx("span", { ref: sizer, className: styles.sizer, "aria-hidden": "true", children: name }), _jsx("span", { className: styles.swapStack, "aria-hidden": "true", children: _jsx(SwapText, { value: name, reduced: reduced }) }), _jsx("span", { className: styles.srOnly, children: name })] });
|
|
88
|
+
}
|
|
89
|
+
export function CodeBlock({ code, filename, language = "tsx", maxLines }) {
|
|
90
|
+
const displayLanguage = normaliseLanguage(language);
|
|
91
|
+
const reduced = useReducedMotion() ?? false;
|
|
92
|
+
const preId = useId();
|
|
93
|
+
const lineCount = code.split("\n").length;
|
|
94
|
+
const collapsible = maxLines != null && maxLines > 0 && lineCount > maxLines;
|
|
95
|
+
const [expanded, setExpanded] = useState(false);
|
|
96
|
+
const open = !collapsible || expanded;
|
|
97
|
+
const preRef = useRef(null);
|
|
98
|
+
const measured = useRef(null);
|
|
99
|
+
// Before the first measurement the clip height comes from CSS, so the server render is already collapsed.
|
|
100
|
+
const height = useMotionValue(open ? "auto" : "var(--code-collapsed)");
|
|
101
|
+
const target = useRef({ open, reduced });
|
|
102
|
+
const settleRef = useRef(() => { });
|
|
103
|
+
// The source area follows its content on a spring: expanding, collapsing, and new code all resize smoothly.
|
|
104
|
+
useLayoutEffect(() => {
|
|
105
|
+
const pre = preRef.current;
|
|
106
|
+
if (!pre)
|
|
107
|
+
return;
|
|
108
|
+
const settle = (instant) => {
|
|
109
|
+
const sizes = measured.current;
|
|
110
|
+
if (!sizes)
|
|
111
|
+
return;
|
|
112
|
+
const next = target.current.open ? sizes.full : sizes.collapsed;
|
|
113
|
+
if (instant || target.current.reduced || typeof height.get() !== "number")
|
|
114
|
+
height.jump(next);
|
|
115
|
+
else
|
|
116
|
+
animate(height, next, motionTokens.spring.smooth);
|
|
117
|
+
};
|
|
118
|
+
const observer = new ResizeObserver(() => {
|
|
119
|
+
const style = getComputedStyle(pre);
|
|
120
|
+
const full = pre.offsetHeight;
|
|
121
|
+
const collapsed = maxLines ? Math.min(full, Math.round(maxLines * parseFloat(style.lineHeight) + parseFloat(style.paddingTop) + parseFloat(style.paddingBottom))) : full;
|
|
122
|
+
const first = !measured.current;
|
|
123
|
+
measured.current = { full, collapsed };
|
|
124
|
+
settle(first);
|
|
125
|
+
});
|
|
126
|
+
observer.observe(pre);
|
|
127
|
+
settleRef.current = settle;
|
|
128
|
+
return () => observer.disconnect();
|
|
129
|
+
}, [height, maxLines]);
|
|
130
|
+
useLayoutEffect(() => { target.current = { open, reduced }; settleRef.current(false); }, [open, reduced]);
|
|
131
|
+
const expandLabels = [`Show all ${lineCount} lines`, "Show fewer lines"];
|
|
132
|
+
return (_jsxs("section", { className: styles.block, "aria-label": filename ? `${filename} source code` : `${displayLanguage} source code`, style: maxLines ? { "--code-lines": maxLines } : undefined, children: [_jsxs("header", { className: styles.header, children: [_jsxs("div", { className: styles.file, children: [_jsx(FileCode2, { size: 16, strokeWidth: 1.75, "aria-hidden": "true" }), _jsx(FileName, { name: filename ?? "Source code", reduced: reduced }), _jsx("span", { className: styles.language, children: displayLanguage })] }), _jsx(CopyButton, { value: code, label: "Copy code" })] }), _jsx(motion.div, { className: styles.viewport, style: { height }, children: _jsx("pre", { ref: preRef, id: preId, className: styles.pre, tabIndex: 0, "aria-label": "Selectable source code", children: _jsx(AnimatePresence, { initial: false, mode: "popLayout", children: _jsx(motion.code, { className: styles.code, initial: reduced ? false : { opacity: 0, y: 4 }, animate: { opacity: 1, y: 0 }, exit: reduced ? { opacity: 0, transition: { duration: 0 } } : { opacity: 0, transition: textExit }, transition: reduced ? { duration: 0 } : textEnter, children: highlight(code, displayLanguage) }, code) }) }) }), collapsible && _jsxs("button", { type: "button", className: styles.expand, "aria-expanded": expanded, "aria-controls": preId, onClick: () => setExpanded(value => !value), children: [_jsxs("span", { className: styles.swap, "aria-hidden": "true", children: [expandLabels.map(text => _jsx("span", { className: styles.reserve, children: text }, text)), _jsx("span", { className: styles.swapStack, children: _jsx(SwapText, { value: expandLabels[expanded ? 1 : 0], reduced: reduced }) })] }), _jsx("span", { className: styles.srOnly, children: expandLabels[expanded ? 1 : 0] }), _jsx(motion.span, { className: styles.chevron, "aria-hidden": "true", initial: false, animate: { rotate: expanded ? 180 : 0 }, transition: reduced ? { duration: 0 } : motionTokens.spring.snappy, children: _jsx(ChevronDown, { size: 16, strokeWidth: 1.75 }) })] })] }));
|
|
133
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.block { width: 100%; min-width: 0; max-width: 100%; overflow: hidden; border: 1px solid var(--border); border-radius: var(--radius-container); background: var(--surface); }
|
|
2
|
+
.header { display: flex; min-height: 52px; align-items: center; justify-content: space-between; gap: var(--space-group); border-bottom: 1px solid var(--border-subtle); padding: var(--space-related) var(--space-group) var(--space-related) var(--space-inset); background: var(--surface-raised); }
|
|
3
|
+
/* Baseline alignment keeps the smaller mono language label on the file name's baseline; the icon centres on its own. */
|
|
4
|
+
.file { display: flex; min-width: 0; align-items: baseline; gap: var(--space-related); color: var(--text-secondary); font-family: var(--font-body); font-size: var(--text-sm); font-weight: 500; letter-spacing: var(--tracking-body); line-height: var(--leading-body); }
|
|
5
|
+
.file > svg { flex: none; align-self: center; color: var(--text-muted); }
|
|
6
|
+
.filename { position: relative; min-width: 0; overflow: hidden; color: var(--foreground); }
|
|
7
|
+
/* Changing text stacks old and new words in one cell; reserve spans hold the widest label so the cell never snaps. */
|
|
8
|
+
.swap { display: inline-grid; min-width: 0; white-space: nowrap; }
|
|
9
|
+
.swap > span, .swapStack > span { grid-area: 1 / 1; min-width: 0; }
|
|
10
|
+
.swapStack { display: grid; min-width: 0; }
|
|
11
|
+
.swapText { display: block; overflow: hidden; text-overflow: ellipsis; }
|
|
12
|
+
.reserve { visibility: hidden; }
|
|
13
|
+
.sizer { position: absolute; top: 0; left: 0; white-space: nowrap; visibility: hidden; pointer-events: none; }
|
|
14
|
+
.srOnly { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
15
|
+
.language { flex: none; color: var(--text-muted); font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; font-size: var(--text-xs); font-weight: 400; }
|
|
16
|
+
.language::before { content: "·"; margin-right: var(--space-related); color: var(--border-strong); }
|
|
17
|
+
/* The source area follows its content height on a spring. Before it measures, a collapsed block clips from CSS. */
|
|
18
|
+
.viewport { --code-collapsed: calc(var(--code-lines, 0) * var(--text-sm) * 1.7 + var(--space-comfort) * 2); overflow: hidden; }
|
|
19
|
+
.pre { position: relative; overflow: auto; margin: 0; padding: var(--space-comfort); color: var(--foreground); font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, "Liberation Mono", monospace; font-size: var(--text-sm); font-variant-ligatures: none; line-height: 1.7; tab-size: 2; white-space: pre; }
|
|
20
|
+
/* Block so new source can rise in with a transform; inline code ignores transforms. */
|
|
21
|
+
.code { display: block; }
|
|
22
|
+
.expand { display: flex; width: 100%; min-height: 44px; align-items: center; justify-content: center; gap: var(--space-related); border: 0; border-top: 1px solid var(--border-subtle); padding: 0 var(--space-inset); background: var(--surface-raised); color: var(--text-secondary); font: inherit; font-size: var(--text-sm); font-weight: 500; cursor: pointer; transition: color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard); }
|
|
23
|
+
.chevron { display: grid; flex: none; place-items: center; color: var(--text-muted); }
|
|
24
|
+
/* Each role has contrast in both themes; color supports, but never replaces, source text. */
|
|
25
|
+
.comment { color: var(--text-muted); font-style: italic; }
|
|
26
|
+
.string { color: oklch(46% .13 150); }
|
|
27
|
+
.number { color: oklch(50% .14 55); }
|
|
28
|
+
.keyword { color: oklch(48% .15 285); }
|
|
29
|
+
.type { color: oklch(46% .13 230); }
|
|
30
|
+
.function { color: oklch(43% .12 25); }
|
|
31
|
+
.property { color: oklch(44% .12 85); }
|
|
32
|
+
.tag { color: oklch(46% .13 230); }
|
|
33
|
+
.punctuation { color: var(--text-secondary); }
|
|
34
|
+
:global(:root[data-theme="dark"]) .string { color: oklch(77% .15 150); }
|
|
35
|
+
:global(:root[data-theme="dark"]) .number { color: oklch(80% .14 75); }
|
|
36
|
+
:global(:root[data-theme="dark"]) .keyword { color: oklch(78% .16 285); }
|
|
37
|
+
:global(:root[data-theme="dark"]) .type { color: oklch(79% .13 230); }
|
|
38
|
+
:global(:root[data-theme="dark"]) .function { color: oklch(80% .13 25); }
|
|
39
|
+
:global(:root[data-theme="dark"]) .property { color: oklch(79% .12 85); }
|
|
40
|
+
:global(:root[data-theme="dark"]) .tag { color: oklch(79% .13 230); }
|
|
41
|
+
@media (hover: hover) and (pointer: fine) { .expand:hover { background: var(--surface-muted); color: var(--foreground); } .expand:hover .chevron { color: var(--foreground); } }
|
|
42
|
+
@media (max-width: 420px) { .header { padding-left: var(--space-group); } .header :global(button) { width: var(--control-height-sm); padding-inline: 0; } .header :global(button) > span:last-of-type { display: none; } .viewport { --code-collapsed: calc(var(--code-lines, 0) * var(--text-xs) * 1.7 + var(--space-inset) * 2); } .pre { padding: var(--space-inset); font-size: var(--text-xs); } }
|
|
43
|
+
@media (prefers-reduced-motion: reduce) { .expand { transition: none; } }
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type ColorFormat = "hex" | "rgb" | "hsl" | "oklch";
|
|
2
|
+
export interface ColorSwatch {
|
|
3
|
+
id: string;
|
|
4
|
+
color: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A color field whose swatch grows into a full picker. Pick saturation and brightness on the area, hue and opacity on the sliders, or type a value
|
|
8
|
+
* in hex, RGB, HSL, or OKLCH; the format button morphs the text between them. The eyedropper appears where the browser supports it, saved
|
|
9
|
+
* swatches can be added, applied, dragged or moved with Alt and the arrow keys, and removed with Delete. A contrast readout compares the color with
|
|
10
|
+
* the background it will sit on. Arrow keys move every thumb, Shift takes bigger steps, and Escape closes the panel.
|
|
11
|
+
*/
|
|
12
|
+
export interface ColorPickerProps {
|
|
13
|
+
/** Any color the picker can read: hex, rgb(), hsl(), or oklch(). */
|
|
14
|
+
value?: string;
|
|
15
|
+
defaultValue?: string;
|
|
16
|
+
/** Receives the color as hex, with two alpha digits when it is not opaque. */
|
|
17
|
+
onValueChange?: (hex: string) => void;
|
|
18
|
+
/** The background the color will sit on, for the contrast readout. */
|
|
19
|
+
background?: string;
|
|
20
|
+
/** Name shown on the swatch, such as "Accent". */
|
|
21
|
+
label?: string;
|
|
22
|
+
swatches?: ColorSwatch[];
|
|
23
|
+
defaultSwatches?: ColorSwatch[];
|
|
24
|
+
onSwatchesChange?: (swatches: ColorSwatch[]) => void;
|
|
25
|
+
/** Most saved swatches. Saving past it drops the oldest. */
|
|
26
|
+
maxSwatches?: number;
|
|
27
|
+
defaultFormat?: ColorFormat;
|
|
28
|
+
className?: string;
|
|
29
|
+
}
|
|
30
|
+
export type Hsva = {
|
|
31
|
+
h: number;
|
|
32
|
+
s: number;
|
|
33
|
+
v: number;
|
|
34
|
+
a: number;
|
|
35
|
+
};
|
|
36
|
+
export declare function toHex(hsva: Hsva): string;
|
|
37
|
+
/** Reads hex, rgb(), hsl(), and oklch() in modern or comma syntax. Returns null for anything else. */
|
|
38
|
+
export declare function parseColor(input: string, hue?: number): Hsva | null;
|
|
39
|
+
export declare function ColorPicker({ value, defaultValue, onValueChange, background, label, swatches: swatchesProp, defaultSwatches, onSwatchesChange, maxSwatches, defaultFormat, className, }: ColorPickerProps): import("react").JSX.Element;
|
|
40
|
+
export default ColorPicker;
|