@nocoo/basalt 2.1.2 → 2.1.8
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/ai/INTEGRATION.md +19 -1
- package/ai/USAGE.md +1 -1
- package/ai/registry.json +81 -81
- package/dist/charts/charts.d.ts +1 -1
- package/dist/charts/charts.js +3 -16
- package/dist/charts/charts.js.map +1 -1
- package/dist/charts/custom-chart.d.ts +1 -1
- package/dist/charts/custom-chart.js +3 -16
- package/dist/charts/custom-chart.js.map +1 -1
- package/dist/charts/grouped-bar.d.ts +1 -1
- package/dist/charts/grouped-bar.js +11 -48
- package/dist/charts/grouped-bar.js.map +1 -1
- package/dist/charts/heatmap-calendar.js +80 -136
- package/dist/charts/heatmap-calendar.js.map +1 -1
- package/dist/charts/slot-bar.js +2 -12
- package/dist/charts/slot-bar.js.map +1 -1
- package/dist/charts/stat-card.js +2 -7
- package/dist/charts/stat-card.js.map +1 -1
- package/dist/charts/timeseries.d.ts +1 -1
- package/dist/charts/timeseries.js +3 -16
- package/dist/charts/timeseries.js.map +1 -1
- package/dist/charts/tooltip.js +13 -51
- package/dist/charts/tooltip.js.map +1 -1
- package/dist/components/autocomplete.d.ts +1 -1
- package/dist/components/autocomplete.js +3 -16
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/banner.js +28 -28
- package/dist/components/banner.js.map +1 -1
- package/dist/components/button.js +8 -9
- package/dist/components/button.js.map +1 -1
- package/dist/components/chat-composer.js +1 -2
- package/dist/components/chat-composer.js.map +1 -1
- package/dist/components/checkbox.js +50 -82
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/code.js +1 -1
- package/dist/components/code.js.map +1 -1
- package/dist/components/combobox.d.ts +1 -1
- package/dist/components/combobox.js +3 -16
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.js +1 -1
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/context-menu.d.ts +1 -67
- package/dist/components/context-menu.js.map +1 -1
- package/dist/components/data-table.js +112 -124
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.js +236 -245
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/delete-resource.js +1 -1
- package/dist/components/delete-resource.js.map +1 -1
- package/dist/components/dock.js +15 -16
- package/dist/components/dock.js.map +1 -1
- package/dist/components/field.js +20 -23
- package/dist/components/field.js.map +1 -1
- package/dist/components/layer-card.d.ts +1 -1
- package/dist/components/layer-card.js +44 -51
- package/dist/components/layer-card.js.map +1 -1
- package/dist/components/skeleton-line.d.ts +2 -2
- package/dist/components/skeleton-line.js +1 -1
- package/dist/components/skeleton-line.js.map +1 -1
- package/dist/components/switch.js +46 -78
- package/dist/components/switch.js.map +1 -1
- package/dist/components/toggle-group.js +2 -2
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle.js +1 -1
- package/dist/components/toggle.js.map +1 -1
- package/dist/components/tooltip.js +14 -13
- package/dist/components/tooltip.js.map +1 -1
- package/dist/providers/accent.js +89 -198
- package/dist/providers/accent.js.map +1 -1
- package/dist/providers/theme.js +46 -144
- package/dist/providers/theme.js.map +1 -1
- package/dist/styles/standalone.css +37 -13
- package/dist/utils/preference-store.d.ts +16 -0
- package/dist/utils/preference-store.js +106 -0
- package/dist/utils/preference-store.js.map +1 -0
- package/dist/utils/selection-indicator.js +1 -1
- package/dist/utils/selection-indicator.js.map +1 -1
- package/dist/utils/use-checkable-group.d.ts +19 -0
- package/dist/utils/use-checkable-group.js +61 -0
- package/dist/utils/use-checkable-group.js.map +1 -0
- package/package.json +2 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.js","names":[],"sources":["../../src/components/tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\ntype RadixTooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\ntype RadixTooltipProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>;\ntype RadixTooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\ntype RadixTooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>;\n\nexport interface TooltipProviderProps\n\textends Omit<\n\t\tRadixTooltipProviderProps,\n\t\t\"children\" | \"delayDuration\" | \"skipDelayDuration\" | \"disableHoverableContent\"\n\t> {\n\t/**\n\t * Application or component tree wrapped by the tooltip provider context.\n\t */\n\tchildren: React.ReactNode;\n\t/**\n\t * Default delay before tooltips open when pointer enters a trigger, in milliseconds.\n\t * Can be overridden per tooltip instance via Tooltip.\n\t * @default 700\n\t */\n\tdelayDuration?: RadixTooltipProviderProps[\"delayDuration\"];\n\t/**\n\t * Duration in milliseconds a user has to enter another trigger without incurring the opening delay again.\n\t * @default 300\n\t */\n\tskipDelayDuration?: RadixTooltipProviderProps[\"skipDelayDuration\"];\n\t/**\n\t * When true, moving pointer into tooltip content closes the tooltip as pointer leaves trigger.\n\t * @default false\n\t */\n\tdisableHoverableContent?: RadixTooltipProviderProps[\"disableHoverableContent\"];\n}\n\nexport const TooltipProvider: React.FC<TooltipProviderProps> = TooltipPrimitive.Provider;\n\nexport interface TooltipProps\n\textends Omit<\n\t\tRadixTooltipProps,\n\t\t| \"children\"\n\t\t| \"open\"\n\t\t| \"defaultOpen\"\n\t\t| \"onOpenChange\"\n\t\t| \"delayDuration\"\n\t\t| \"disableHoverableContent\"\n\t> {\n\t/**\n\t * Content elements rendered within the tooltip root, typically a TooltipTrigger and TooltipContent.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Controlled open state of the tooltip.\n\t */\n\topen?: RadixTooltipProps[\"open\"];\n\t/**\n\t * Uncontrolled initial open state of the tooltip.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixTooltipProps[\"defaultOpen\"];\n\t/**\n\t * Callback called when the open state changes.\n\t */\n\tonOpenChange?: RadixTooltipProps[\"onOpenChange\"];\n\t/**\n\t * Delay before the tooltip opens, in milliseconds. Overrides TooltipProvider delayDuration.\n\t * Defaults to provider value (typically 700ms).\n\t */\n\tdelayDuration?: RadixTooltipProps[\"delayDuration\"];\n\t/**\n\t * When true, moving pointer into tooltip content closes the tooltip as pointer leaves trigger.\n\t * Overrides TooltipProvider setting.\n\t */\n\tdisableHoverableContent?: RadixTooltipProps[\"disableHoverableContent\"];\n}\n\nexport const Tooltip: React.FC<TooltipProps> = TooltipPrimitive.Root;\n\nexport interface TooltipTriggerProps extends Omit<RadixTooltipTriggerProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * TooltipTrigger forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixTooltipTriggerProps[\"asChild\"];\n}\n\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\nexport interface TooltipContentProps\n\textends Omit<\n\t\tRadixTooltipContentProps,\n\t\t| \"aria-label\"\n\t\t| \"onEscapeKeyDown\"\n\t\t| \"onPointerDownOutside\"\n\t\t| \"side\"\n\t\t| \"sideOffset\"\n\t\t| \"align\"\n\t\t| \"alignOffset\"\n\t\t| \"avoidCollisions\"\n\t\t| \"collisionBoundary\"\n\t\t| \"collisionPadding\"\n\t\t| \"arrowPadding\"\n\t\t| \"sticky\"\n\t\t| \"hideWhenDetached\"\n\t\t| \"updatePositionStrategy\"\n\t\t| \"forceMount\"\n\t\t| \"asChild\"\n\t> {\n\t/**\n\t * A more descriptive accessible label announced by screen readers.\n\t */\n\t\"aria-label\"?: RadixTooltipContentProps[\"aria-label\"];\n\t/**\n\t * Callback fired when the Escape key is down on the tooltip content layer. Can be prevented.\n\t */\n\tonEscapeKeyDown?: RadixTooltipContentProps[\"onEscapeKeyDown\"];\n\t/**\n\t * Callback fired when a pointerdown event happens outside the bounds of the tooltip. Can be prevented.\n\t */\n\tonPointerDownOutside?: RadixTooltipContentProps[\"onPointerDownOutside\"];\n\t/**\n\t * Preferred placement side relative to trigger.\n\t * @default \"top\"\n\t */\n\tside?: RadixTooltipContentProps[\"side\"];\n\t/**\n\t * Distance in pixels between trigger and floating content panel.\n\t * @default 4\n\t */\n\tsideOffset?: RadixTooltipContentProps[\"sideOffset\"];\n\t/**\n\t * Preferred alignment along the side axis.\n\t * @default \"center\"\n\t */\n\talign?: RadixTooltipContentProps[\"align\"];\n\t/**\n\t * Offset in pixels from the start or end alignment position.\n\t * @default 0\n\t */\n\talignOffset?: RadixTooltipContentProps[\"alignOffset\"];\n\t/**\n\t * Whether to reposition content to avoid viewport boundary collisions.\n\t * @default true\n\t */\n\tavoidCollisions?: RadixTooltipContentProps[\"avoidCollisions\"];\n\t/**\n\t * Element or elements bounding boundary collision calculations.\n\t * @default []\n\t */\n\tcollisionBoundary?: RadixTooltipContentProps[\"collisionBoundary\"];\n\t/**\n\t * Virtual padding from collision boundaries in pixels.\n\t * @default 0\n\t */\n\tcollisionPadding?: RadixTooltipContentProps[\"collisionPadding\"];\n\t/**\n\t * Padding in pixels between popper arrow and floating panel edge.\n\t * @default 0\n\t */\n\tarrowPadding?: RadixTooltipContentProps[\"arrowPadding\"];\n\t/**\n\t * Sticky positioning behavior along the align axis when overflowing.\n\t * @default \"partial\"\n\t */\n\tsticky?: RadixTooltipContentProps[\"sticky\"];\n\t/**\n\t * Whether to hide content completely when trigger is fully occluded.\n\t * @default false\n\t */\n\thideWhenDetached?: RadixTooltipContentProps[\"hideWhenDetached\"];\n\t/**\n\t * Strategy used to calculate and update popper position.\n\t * @default \"optimized\"\n\t */\n\tupdatePositionStrategy?: RadixTooltipContentProps[\"updatePositionStrategy\"];\n\t/**\n\t * Force mounting content in DOM for external animation controls.\n\t * When forceMount is true, the content remains mounted even when closed.\n\t * The caller is responsible for visibility transitions and unmounting after animation completes.\n\t */\n\tforceMount?: true;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * TooltipContent forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixTooltipContentProps[\"asChild\"];\n}\n\nexport const TooltipContent = React.forwardRef<\n\tReact.ElementRef<typeof TooltipPrimitive.Content>,\n\tTooltipContentProps\n>(({ className, sideOffset = 4, ...props }, ref) => (\n\t<TooltipPrimitive.Portal forceMount={props.forceMount}>\n\t\t<TooltipPrimitive.Content\n\t\t\tref={ref}\n\t\t\tsideOffset={sideOffset}\n\t\t\tclassName={cn(\n\t\t\t\tOVERLAY_LAYER,\n\t\t\t\tOVERLAY_MOTION,\n\t\t\t\t\"overflow-hidden rounded-basalt-md border border-basalt-border bg-basalt-popover px-
|
|
1
|
+
{"version":3,"file":"tooltip.js","names":[],"sources":["../../src/components/tooltip.tsx"],"sourcesContent":["import * as TooltipPrimitive from \"@radix-ui/react-tooltip\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { BASALT_UI_CLASS } from \"../utils/control-surface\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\ntype RadixTooltipProviderProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Provider>;\ntype RadixTooltipProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>;\ntype RadixTooltipTriggerProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Trigger>;\ntype RadixTooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>;\n\nexport interface TooltipProviderProps\n\textends Omit<\n\t\tRadixTooltipProviderProps,\n\t\t\"children\" | \"delayDuration\" | \"skipDelayDuration\" | \"disableHoverableContent\"\n\t> {\n\t/**\n\t * Application or component tree wrapped by the tooltip provider context.\n\t */\n\tchildren: React.ReactNode;\n\t/**\n\t * Default delay before tooltips open when pointer enters a trigger, in milliseconds.\n\t * Can be overridden per tooltip instance via Tooltip.\n\t * @default 700\n\t */\n\tdelayDuration?: RadixTooltipProviderProps[\"delayDuration\"];\n\t/**\n\t * Duration in milliseconds a user has to enter another trigger without incurring the opening delay again.\n\t * @default 300\n\t */\n\tskipDelayDuration?: RadixTooltipProviderProps[\"skipDelayDuration\"];\n\t/**\n\t * When true, moving pointer into tooltip content closes the tooltip as pointer leaves trigger.\n\t * @default false\n\t */\n\tdisableHoverableContent?: RadixTooltipProviderProps[\"disableHoverableContent\"];\n}\n\nexport const TooltipProvider: React.FC<TooltipProviderProps> = TooltipPrimitive.Provider;\n\nexport interface TooltipProps\n\textends Omit<\n\t\tRadixTooltipProps,\n\t\t| \"children\"\n\t\t| \"open\"\n\t\t| \"defaultOpen\"\n\t\t| \"onOpenChange\"\n\t\t| \"delayDuration\"\n\t\t| \"disableHoverableContent\"\n\t> {\n\t/**\n\t * Content elements rendered within the tooltip root, typically a TooltipTrigger and TooltipContent.\n\t */\n\tchildren?: React.ReactNode;\n\t/**\n\t * Controlled open state of the tooltip.\n\t */\n\topen?: RadixTooltipProps[\"open\"];\n\t/**\n\t * Uncontrolled initial open state of the tooltip.\n\t * @default false\n\t */\n\tdefaultOpen?: RadixTooltipProps[\"defaultOpen\"];\n\t/**\n\t * Callback called when the open state changes.\n\t */\n\tonOpenChange?: RadixTooltipProps[\"onOpenChange\"];\n\t/**\n\t * Delay before the tooltip opens, in milliseconds. Overrides TooltipProvider delayDuration.\n\t * Defaults to provider value (typically 700ms).\n\t */\n\tdelayDuration?: RadixTooltipProps[\"delayDuration\"];\n\t/**\n\t * When true, moving pointer into tooltip content closes the tooltip as pointer leaves trigger.\n\t * Overrides TooltipProvider setting.\n\t */\n\tdisableHoverableContent?: RadixTooltipProps[\"disableHoverableContent\"];\n}\n\nexport const Tooltip: React.FC<TooltipProps> = TooltipPrimitive.Root;\n\nexport interface TooltipTriggerProps extends Omit<RadixTooltipTriggerProps, \"asChild\"> {\n\t/**\n\t * Change the default rendered button element to the child element, merging props and behavior.\n\t * TooltipTrigger forwards ref to HTMLButtonElement and inherits native button attributes.\n\t * @default false\n\t */\n\tasChild?: RadixTooltipTriggerProps[\"asChild\"];\n}\n\nexport const TooltipTrigger = TooltipPrimitive.Trigger;\n\nexport interface TooltipContentProps\n\textends Omit<\n\t\tRadixTooltipContentProps,\n\t\t| \"aria-label\"\n\t\t| \"onEscapeKeyDown\"\n\t\t| \"onPointerDownOutside\"\n\t\t| \"side\"\n\t\t| \"sideOffset\"\n\t\t| \"align\"\n\t\t| \"alignOffset\"\n\t\t| \"avoidCollisions\"\n\t\t| \"collisionBoundary\"\n\t\t| \"collisionPadding\"\n\t\t| \"arrowPadding\"\n\t\t| \"sticky\"\n\t\t| \"hideWhenDetached\"\n\t\t| \"updatePositionStrategy\"\n\t\t| \"forceMount\"\n\t\t| \"asChild\"\n\t> {\n\t/**\n\t * A more descriptive accessible label announced by screen readers.\n\t */\n\t\"aria-label\"?: RadixTooltipContentProps[\"aria-label\"];\n\t/**\n\t * Callback fired when the Escape key is down on the tooltip content layer. Can be prevented.\n\t */\n\tonEscapeKeyDown?: RadixTooltipContentProps[\"onEscapeKeyDown\"];\n\t/**\n\t * Callback fired when a pointerdown event happens outside the bounds of the tooltip. Can be prevented.\n\t */\n\tonPointerDownOutside?: RadixTooltipContentProps[\"onPointerDownOutside\"];\n\t/**\n\t * Preferred placement side relative to trigger.\n\t * @default \"top\"\n\t */\n\tside?: RadixTooltipContentProps[\"side\"];\n\t/**\n\t * Distance in pixels between trigger and floating content panel.\n\t * @default 4\n\t */\n\tsideOffset?: RadixTooltipContentProps[\"sideOffset\"];\n\t/**\n\t * Preferred alignment along the side axis.\n\t * @default \"center\"\n\t */\n\talign?: RadixTooltipContentProps[\"align\"];\n\t/**\n\t * Offset in pixels from the start or end alignment position.\n\t * @default 0\n\t */\n\talignOffset?: RadixTooltipContentProps[\"alignOffset\"];\n\t/**\n\t * Whether to reposition content to avoid viewport boundary collisions.\n\t * @default true\n\t */\n\tavoidCollisions?: RadixTooltipContentProps[\"avoidCollisions\"];\n\t/**\n\t * Element or elements bounding boundary collision calculations.\n\t * @default []\n\t */\n\tcollisionBoundary?: RadixTooltipContentProps[\"collisionBoundary\"];\n\t/**\n\t * Virtual padding from collision boundaries in pixels.\n\t * @default 0\n\t */\n\tcollisionPadding?: RadixTooltipContentProps[\"collisionPadding\"];\n\t/**\n\t * Padding in pixels between popper arrow and floating panel edge.\n\t * @default 0\n\t */\n\tarrowPadding?: RadixTooltipContentProps[\"arrowPadding\"];\n\t/**\n\t * Sticky positioning behavior along the align axis when overflowing.\n\t * @default \"partial\"\n\t */\n\tsticky?: RadixTooltipContentProps[\"sticky\"];\n\t/**\n\t * Whether to hide content completely when trigger is fully occluded.\n\t * @default false\n\t */\n\thideWhenDetached?: RadixTooltipContentProps[\"hideWhenDetached\"];\n\t/**\n\t * Strategy used to calculate and update popper position.\n\t * @default \"optimized\"\n\t */\n\tupdatePositionStrategy?: RadixTooltipContentProps[\"updatePositionStrategy\"];\n\t/**\n\t * Force mounting content in DOM for external animation controls.\n\t * When forceMount is true, the content remains mounted even when closed.\n\t * The caller is responsible for visibility transitions and unmounting after animation completes.\n\t */\n\tforceMount?: true;\n\t/**\n\t * Change the default rendered div element to the child element, merging props and behavior.\n\t * TooltipContent forwards ref to HTMLDivElement and inherits native div attributes.\n\t * @default false\n\t */\n\tasChild?: RadixTooltipContentProps[\"asChild\"];\n}\n\nexport const TooltipContent = React.forwardRef<\n\tReact.ElementRef<typeof TooltipPrimitive.Content>,\n\tTooltipContentProps\n>(({ className, sideOffset = 4, ...props }, ref) => (\n\t<TooltipPrimitive.Portal forceMount={props.forceMount}>\n\t\t<TooltipPrimitive.Content\n\t\t\tref={ref}\n\t\t\tsideOffset={sideOffset}\n\t\t\tclassName={cn(\n\t\t\t\tBASALT_UI_CLASS,\n\t\t\t\tOVERLAY_LAYER,\n\t\t\t\tOVERLAY_MOTION,\n\t\t\t\t\"overflow-hidden rounded-basalt-md border border-basalt-border bg-basalt-popover px-2 py-1 text-xs font-normal leading-4 text-basalt-popover-foreground shadow-md\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t</TooltipPrimitive.Portal>\n));\nTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n"],"mappings":";;;;;;;;AAsCA,IAAa,IAAkD,EAAiB,UAyCnE,IAAkC,EAAiB,MAWnD,IAAiB,EAAiB,SAuGlC,IAAiB,EAAM,YAGjC,EAAE,cAAW,gBAAa,GAAG,GAAG,KAAS,MAC3C,kBAAC,EAAiB,QAAlB;CAAyB,YAAY,EAAM;CAC1C,UAAA,kBAAC,EAAiB,SAAlB;EACM;EACO;EACZ,WAAW,EACV,GACA,GACA,GACA,oKACA,CACD;EACA,GAAI;CACJ,CAAA;AACuB,CAAA,CACzB;AACD,EAAe,cAAc,EAAiB,QAAQ"}
|
package/dist/providers/accent.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { createPreferenceStore as e } from "../utils/preference-store.js";
|
|
3
|
+
import { createContext as t, useCallback as n, useContext as r, useEffect as i, useMemo as a, useState as o, useSyncExternalStore as s } from "react";
|
|
4
|
+
import { jsx as c } from "react/jsx-runtime";
|
|
4
5
|
//#region src/providers/accent.tsx
|
|
5
|
-
var
|
|
6
|
+
var l = [
|
|
6
7
|
{
|
|
7
8
|
id: "primary",
|
|
8
9
|
label: "Blue",
|
|
@@ -87,7 +88,7 @@ var c = [
|
|
|
87
88
|
light: "210 20% 87%",
|
|
88
89
|
dark: "210 20% 88%"
|
|
89
90
|
}
|
|
90
|
-
],
|
|
91
|
+
], u = /* @__PURE__ */ new Map([
|
|
91
92
|
["jade", "teal"],
|
|
92
93
|
["vermilion", "red"],
|
|
93
94
|
["magenta", "rose"],
|
|
@@ -100,15 +101,15 @@ var c = [
|
|
|
100
101
|
["gold", "amber"],
|
|
101
102
|
["tangerine", "orange"],
|
|
102
103
|
["crimson", "red"]
|
|
103
|
-
]),
|
|
104
|
-
function p(e) {
|
|
105
|
-
let t = l.get(e ?? "") ?? e;
|
|
106
|
-
return c.find((e) => e.id === t) ?? c[0];
|
|
107
|
-
}
|
|
104
|
+
]), d = "primary", f = "basalt-accent", p = t(null);
|
|
108
105
|
function m(e) {
|
|
109
|
-
|
|
106
|
+
let t = u.get(e ?? "") ?? e;
|
|
107
|
+
return l.find((e) => e.id === t) ?? l[0];
|
|
110
108
|
}
|
|
111
109
|
function h(e) {
|
|
110
|
+
return e <= .04045 ? e / 12.92 : ((e + .055) / 1.055) ** 2.4;
|
|
111
|
+
}
|
|
112
|
+
function g(e) {
|
|
112
113
|
let [t, n, r] = e.trim().split(/\s+/);
|
|
113
114
|
return [
|
|
114
115
|
Number(t),
|
|
@@ -116,7 +117,7 @@ function h(e) {
|
|
|
116
117
|
Number(r.replace("%", "")) / 100
|
|
117
118
|
];
|
|
118
119
|
}
|
|
119
|
-
function
|
|
120
|
+
function _(e, t, n) {
|
|
120
121
|
let r = (t) => (t + e / 30) % 12, i = t * Math.min(n, 1 - n), a = (e) => n - i * Math.max(-1, Math.min(r(e) - 3, Math.min(9 - r(e), 1)));
|
|
121
122
|
return [
|
|
122
123
|
255 * a(0),
|
|
@@ -124,22 +125,22 @@ function g(e, t, n) {
|
|
|
124
125
|
255 * a(4)
|
|
125
126
|
];
|
|
126
127
|
}
|
|
127
|
-
function
|
|
128
|
-
return .2126 *
|
|
128
|
+
function v(e) {
|
|
129
|
+
return .2126 * h(e[0] / 255) + .7152 * h(e[1] / 255) + .0722 * h(e[2] / 255);
|
|
129
130
|
}
|
|
130
|
-
function
|
|
131
|
-
let n =
|
|
131
|
+
function y(e, t) {
|
|
132
|
+
let n = v(e), r = v(t);
|
|
132
133
|
return (Math.max(n, r) + .05) / (Math.min(n, r) + .05);
|
|
133
134
|
}
|
|
134
|
-
var
|
|
135
|
+
var b = [
|
|
135
136
|
26,
|
|
136
137
|
26,
|
|
137
138
|
26
|
|
138
|
-
],
|
|
139
|
+
], x = [
|
|
139
140
|
255,
|
|
140
141
|
255,
|
|
141
142
|
255
|
|
142
|
-
],
|
|
143
|
+
], S = [
|
|
143
144
|
[
|
|
144
145
|
238,
|
|
145
146
|
239,
|
|
@@ -160,7 +161,7 @@ var y = [
|
|
|
160
161
|
255,
|
|
161
162
|
255
|
|
162
163
|
]
|
|
163
|
-
],
|
|
164
|
+
], C = [
|
|
164
165
|
[
|
|
165
166
|
23,
|
|
166
167
|
23,
|
|
@@ -182,30 +183,20 @@ var y = [
|
|
|
182
183
|
36
|
|
183
184
|
]
|
|
184
185
|
];
|
|
185
|
-
function
|
|
186
|
+
function w(e, t) {
|
|
186
187
|
return [
|
|
187
188
|
e[0] * e[3] + t[0] * (1 - e[3]),
|
|
188
189
|
e[1] * e[3] + t[1] * (1 - e[3]),
|
|
189
190
|
e[2] * e[3] + t[2] * (1 - e[3])
|
|
190
191
|
];
|
|
191
192
|
}
|
|
192
|
-
function
|
|
193
|
-
let [n, r, i] =
|
|
194
|
-
|
|
195
|
-
let t =
|
|
196
|
-
if (Math.min(...a.map((e) =>
|
|
193
|
+
function T(e, t) {
|
|
194
|
+
let [n, r, i] = g(t ? e.dark : e.light), a = t ? C : S, o = t ? b : x, s = t ? Math.max(Math.round(i * 100), 45) : Math.min(Math.round(i * 100), 60);
|
|
195
|
+
for (let e = s; t ? e <= 85 : e >= 15; e += t ? 1 : -1) {
|
|
196
|
+
let t = _(n, r, e / 100);
|
|
197
|
+
if (Math.min(...a.map((e) => y(t, e))) < 4.55 || y(t, o) < 4.55) continue;
|
|
197
198
|
let i = !0;
|
|
198
|
-
for (let e of a) if (
|
|
199
|
-
i = !1;
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
202
|
-
if (i) return `${n} ${Math.round(r * 100)}% ${e}%`;
|
|
203
|
-
}
|
|
204
|
-
else for (let e = Math.min(Math.round(i * 100), 60); e >= 15; e--) {
|
|
205
|
-
let t = g(n, r, e / 100);
|
|
206
|
-
if (Math.min(...a.map((e) => v(t, e))) < 4.55 || v(t, b) < 4.55) continue;
|
|
207
|
-
let i = !0;
|
|
208
|
-
for (let e of a) if (v(C([...t, .9], e), b) < 4.55) {
|
|
199
|
+
for (let e of a) if (y(w([...t, .9], e), o) < 4.55) {
|
|
209
200
|
i = !1;
|
|
210
201
|
break;
|
|
211
202
|
}
|
|
@@ -213,163 +204,63 @@ function w(e, t) {
|
|
|
213
204
|
}
|
|
214
205
|
return t ? e.dark : e.light;
|
|
215
206
|
}
|
|
216
|
-
function
|
|
217
|
-
let [t, n, r] =
|
|
218
|
-
return
|
|
219
|
-
}
|
|
220
|
-
function E(e, t = !1) {
|
|
221
|
-
typeof document > "u" || D(p(e), t);
|
|
207
|
+
function E(e) {
|
|
208
|
+
let [t, n, r] = g(e), i = _(t, n, r), a = y(i, x);
|
|
209
|
+
return y(i, b) >= a ? "0 0% 10%" : "0 0% 100%";
|
|
222
210
|
}
|
|
223
|
-
function D(e, t) {
|
|
224
|
-
|
|
225
|
-
r.style.setProperty("--basalt-primary", n), r.style.setProperty("--basalt-primary-foreground", T(n)), r.style.setProperty("--basalt-ring", n), r.dataset.accent = e.id;
|
|
211
|
+
function D(e, t = !1) {
|
|
212
|
+
typeof document > "u" || O(m(e), t);
|
|
226
213
|
}
|
|
227
|
-
function O(e) {
|
|
228
|
-
|
|
214
|
+
function O(e, t) {
|
|
215
|
+
let n = T(e, t), r = document.documentElement;
|
|
216
|
+
r.style.setProperty("--basalt-primary", n), r.style.setProperty("--basalt-primary-foreground", E(n)), r.style.setProperty("--basalt-ring", n), r.dataset.accent = e.id;
|
|
229
217
|
}
|
|
230
218
|
function k(e) {
|
|
231
|
-
|
|
232
|
-
return typeof window > "u" || !window.localStorage ? { status: "error" } : {
|
|
233
|
-
status: "success",
|
|
234
|
-
value: window.localStorage.getItem(e)
|
|
235
|
-
};
|
|
236
|
-
} catch {
|
|
237
|
-
return { status: "error" };
|
|
238
|
-
}
|
|
219
|
+
return typeof e == "string" && (l.some((t) => t.id === e) || u.has(e));
|
|
239
220
|
}
|
|
240
|
-
function A(e
|
|
241
|
-
try {
|
|
242
|
-
return typeof window > "u" || !window.localStorage ? !1 : (window.localStorage.setItem(e, t), !0);
|
|
243
|
-
} catch {
|
|
244
|
-
return !1;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
function j(e) {
|
|
248
|
-
if (!e) return !0;
|
|
249
|
-
try {
|
|
250
|
-
if (typeof window < "u" && window.localStorage) return e === window.localStorage;
|
|
251
|
-
} catch {
|
|
252
|
-
return !1;
|
|
253
|
-
}
|
|
254
|
-
return !1;
|
|
255
|
-
}
|
|
256
|
-
var M = "basalt:accent-change";
|
|
257
|
-
function N(e, t, n) {
|
|
258
|
-
let r = e, i = p(t).id, a = n, o = i, s = !1, c = !1;
|
|
259
|
-
if (a) {
|
|
260
|
-
let e = k(r);
|
|
261
|
-
e.status === "success" && O(e.value) && (o = p(e.value).id, s = !0);
|
|
262
|
-
}
|
|
263
|
-
let l = /* @__PURE__ */ new Set(), u = () => {
|
|
264
|
-
for (let e of l) e();
|
|
265
|
-
}, d = (e) => {
|
|
266
|
-
if (!a) return;
|
|
267
|
-
let t = e;
|
|
268
|
-
if (!t.detail || t.detail.key !== r) return;
|
|
269
|
-
let { value: n, writeSucceeded: i } = t.detail;
|
|
270
|
-
c = !i, o = n, s = !0, u();
|
|
271
|
-
}, f = (e) => {
|
|
272
|
-
if (!a) return;
|
|
273
|
-
let t = e;
|
|
274
|
-
if ("key" in t && t.key !== void 0) {
|
|
275
|
-
if (!j(t.storageArea) || t.key !== null && t.key !== r) return;
|
|
276
|
-
c = !1;
|
|
277
|
-
let e = t.newValue;
|
|
278
|
-
if (e == null || !O(e)) {
|
|
279
|
-
o = i, s = !1, u();
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
o = p(e).id, s = !0, u();
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
if (c) return;
|
|
286
|
-
let n = k(r);
|
|
287
|
-
n.status !== "error" && (O(n.value) ? (o = p(n.value).id, s = !0, u()) : (o = i, s = !1, u()));
|
|
288
|
-
}, m = null, h = () => {
|
|
289
|
-
typeof window > "u" || l.size === 1 && !m && (window.addEventListener("storage", f), window.addEventListener(M, d), m = () => {
|
|
290
|
-
window.removeEventListener("storage", f), window.removeEventListener(M, d), m = null;
|
|
291
|
-
});
|
|
292
|
-
}, g = () => {
|
|
293
|
-
l.size === 0 && m && m();
|
|
294
|
-
};
|
|
295
|
-
return {
|
|
296
|
-
getSnapshot: () => o,
|
|
297
|
-
subscribe: (e) => (l.add(e), h(), () => {
|
|
298
|
-
l.delete(e), g();
|
|
299
|
-
}),
|
|
300
|
-
setAccent: (e) => {
|
|
301
|
-
let t = p(e).id;
|
|
302
|
-
o = t, s = !0;
|
|
303
|
-
let n = !0;
|
|
304
|
-
if (a) {
|
|
305
|
-
let e = A(r, t);
|
|
306
|
-
if (c = !e, n = e, typeof window < "u") try {
|
|
307
|
-
window.dispatchEvent(new CustomEvent(M, { detail: {
|
|
308
|
-
key: r,
|
|
309
|
-
value: t,
|
|
310
|
-
writeSucceeded: n
|
|
311
|
-
} }));
|
|
312
|
-
} catch {}
|
|
313
|
-
}
|
|
314
|
-
u();
|
|
315
|
-
},
|
|
316
|
-
updateConfig: (e) => {
|
|
317
|
-
let t = r !== e.storageKey, n = a !== e.persist, l = p(e.defaultAccent).id, d = i !== l, f = a;
|
|
318
|
-
if (r = e.storageKey, i = l, a = e.persist, t) {
|
|
319
|
-
if (a) {
|
|
320
|
-
let e = k(r);
|
|
321
|
-
e.status === "success" && (c = !1, O(e.value) ? (o = p(e.value).id, s = !0) : (o = i, s = !1)), u();
|
|
322
|
-
}
|
|
323
|
-
} else if (n) {
|
|
324
|
-
if (!f && a) {
|
|
325
|
-
let e = k(r);
|
|
326
|
-
e.status === "success" && (c = !1, O(e.value) && (o = p(e.value).id, s = !0, u()));
|
|
327
|
-
}
|
|
328
|
-
} else if (d && !s) {
|
|
329
|
-
if (a) {
|
|
330
|
-
let e = k(r);
|
|
331
|
-
e.status === "success" && !O(e.value) && (o = i, u());
|
|
332
|
-
} else o = i, u();
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
function P(e) {
|
|
221
|
+
function A(e) {
|
|
338
222
|
if (typeof e != "string" || !/^\d+(?:\.\d+)?\s+\d+(?:\.\d+)?%\s+\d+(?:\.\d+)?%$/.test(e)) return !1;
|
|
339
|
-
let [t, n, r] =
|
|
223
|
+
let [t, n, r] = g(e);
|
|
340
224
|
return t <= 360 && n <= 1 && r <= 1;
|
|
341
225
|
}
|
|
342
|
-
function
|
|
226
|
+
function j() {
|
|
343
227
|
return typeof document > "u" ? !1 : document.documentElement.classList.contains("dark");
|
|
344
228
|
}
|
|
345
|
-
function
|
|
346
|
-
let
|
|
347
|
-
let t =
|
|
348
|
-
return t &&
|
|
229
|
+
function M({ children: t, paletteOverrides: r, storageKey: u = f, defaultAccent: h = d, persist: g = !0, accent: _, onAccentChange: v, applyToDocument: y = !0 }) {
|
|
230
|
+
let b = _ !== void 0, x = a(() => l.map((e) => {
|
|
231
|
+
let t = r?.[e.id];
|
|
232
|
+
return t && A(t.light) && A(t.dark) ? {
|
|
349
233
|
...e,
|
|
350
234
|
light: t.light,
|
|
351
235
|
dark: t.dark
|
|
352
236
|
} : e;
|
|
353
|
-
}), [
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
237
|
+
}), [r]), [S] = o(() => e({
|
|
238
|
+
storageKey: u,
|
|
239
|
+
defaultValue: h,
|
|
240
|
+
persist: g,
|
|
241
|
+
isValid: k,
|
|
242
|
+
normalize: (e) => m(e).id,
|
|
243
|
+
eventName: "basalt:accent-change"
|
|
244
|
+
}));
|
|
245
|
+
i(() => {
|
|
246
|
+
S.updateConfig({
|
|
247
|
+
storageKey: u,
|
|
248
|
+
defaultValue: h,
|
|
249
|
+
persist: g
|
|
359
250
|
});
|
|
360
251
|
}, [
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
252
|
+
S,
|
|
253
|
+
u,
|
|
254
|
+
h,
|
|
255
|
+
g
|
|
365
256
|
]);
|
|
366
|
-
let
|
|
367
|
-
|
|
368
|
-
if (!
|
|
257
|
+
let C = n(() => m(h).id, [h]), w = s(S.subscribe, S.getSnapshot, C), T = b ? m(_).id : w;
|
|
258
|
+
i(() => {
|
|
259
|
+
if (!y || typeof document > "u") return;
|
|
369
260
|
let e = () => {
|
|
370
|
-
let e =
|
|
371
|
-
for (let t of
|
|
372
|
-
|
|
261
|
+
let e = j();
|
|
262
|
+
for (let t of x) document.documentElement.style.setProperty(t.token, e ? t.dark : t.light);
|
|
263
|
+
O(x.find((e) => e.id === T) ?? x[0], e);
|
|
373
264
|
};
|
|
374
265
|
e();
|
|
375
266
|
let t = new MutationObserver(e);
|
|
@@ -378,41 +269,41 @@ function I({ children: e, paletteOverrides: n, storageKey: l = d, defaultAccent:
|
|
|
378
269
|
attributeFilter: ["class"]
|
|
379
270
|
}), () => t.disconnect();
|
|
380
271
|
}, [
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
272
|
+
T,
|
|
273
|
+
y,
|
|
274
|
+
x
|
|
384
275
|
]);
|
|
385
|
-
let
|
|
386
|
-
let t =
|
|
387
|
-
if (
|
|
388
|
-
|
|
276
|
+
let E = n((e) => {
|
|
277
|
+
let t = m(e).id;
|
|
278
|
+
if (b) {
|
|
279
|
+
v?.(t);
|
|
389
280
|
return;
|
|
390
281
|
}
|
|
391
|
-
|
|
282
|
+
S.setValue(t), v?.(t);
|
|
392
283
|
}, [
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
]),
|
|
397
|
-
accent:
|
|
398
|
-
setAccent:
|
|
399
|
-
swatches:
|
|
284
|
+
b,
|
|
285
|
+
v,
|
|
286
|
+
S
|
|
287
|
+
]), D = a(() => ({
|
|
288
|
+
accent: T,
|
|
289
|
+
setAccent: E,
|
|
290
|
+
swatches: x
|
|
400
291
|
}), [
|
|
401
|
-
w,
|
|
402
292
|
T,
|
|
403
|
-
|
|
293
|
+
E,
|
|
294
|
+
x
|
|
404
295
|
]);
|
|
405
|
-
return /* @__PURE__ */
|
|
406
|
-
value:
|
|
407
|
-
children:
|
|
296
|
+
return /* @__PURE__ */ c(p.Provider, {
|
|
297
|
+
value: D,
|
|
298
|
+
children: t
|
|
408
299
|
});
|
|
409
300
|
}
|
|
410
|
-
function
|
|
411
|
-
let e =
|
|
301
|
+
function N() {
|
|
302
|
+
let e = r(p);
|
|
412
303
|
if (!e) throw Error("useAccent must be used within AccentProvider");
|
|
413
304
|
return e;
|
|
414
305
|
}
|
|
415
306
|
//#endregion
|
|
416
|
-
export {
|
|
307
|
+
export { l as ACCENT_SWATCHES, M as AccentProvider, d as DEFAULT_ACCENT_ID, E as accentForeground, m as accentSwatchById, D as applyAccent, N as useAccent };
|
|
417
308
|
|
|
418
309
|
//# sourceMappingURL=accent.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accent.js","names":[],"sources":["../../src/providers/accent.tsx"],"sourcesContent":["import {\n\tcreateContext,\n\ttype ReactNode,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseState,\n\tuseSyncExternalStore,\n} from \"react\";\n\nexport type AccentSwatch = {\n\tid: string;\n\tlabel: string;\n\ttoken: string;\n\tlight: string;\n\tdark: string;\n};\n\n/** Twelve candy accents inspired by the translucent iMac and iPhone 5C finishes. */\nexport const ACCENT_SWATCHES: readonly AccentSwatch[] = [\n\t{\n\t\tid: \"primary\",\n\t\tlabel: \"Blue\",\n\t\ttoken: \"--basalt-accent-1\",\n\t\tlight: \"204 88% 62%\",\n\t\tdark: \"204 90% 70%\",\n\t},\n\t{\n\t\tid: \"sky\",\n\t\tlabel: \"Ice\",\n\t\ttoken: \"--basalt-accent-2\",\n\t\tlight: \"191 79% 70%\",\n\t\tdark: \"191 79% 74%\",\n\t},\n\t{\n\t\tid: \"teal\",\n\t\tlabel: \"Bondi\",\n\t\ttoken: \"--basalt-accent-3\",\n\t\tlight: \"182 62% 47%\",\n\t\tdark: \"182 62% 63%\",\n\t},\n\t{\n\t\tid: \"green\",\n\t\tlabel: \"Green\",\n\t\ttoken: \"--basalt-accent-4\",\n\t\tlight: \"113 58% 62%\",\n\t\tdark: \"113 58% 70%\",\n\t},\n\t{\n\t\tid: \"lime\",\n\t\tlabel: \"Lime\",\n\t\ttoken: \"--basalt-accent-5\",\n\t\tlight: \"79 70% 64%\",\n\t\tdark: \"79 70% 70%\",\n\t},\n\t{\n\t\tid: \"amber\",\n\t\tlabel: \"Yellow\",\n\t\ttoken: \"--basalt-accent-6\",\n\t\tlight: \"49 100% 69%\",\n\t\tdark: \"49 100% 73%\",\n\t},\n\t{\n\t\tid: \"orange\",\n\t\tlabel: \"Tangerine\",\n\t\ttoken: \"--basalt-accent-7\",\n\t\tlight: \"27 95% 65%\",\n\t\tdark: \"27 95% 72%\",\n\t},\n\t{\n\t\tid: \"red\",\n\t\tlabel: \"Strawberry\",\n\t\ttoken: \"--basalt-accent-8\",\n\t\tlight: \"5 85% 66%\",\n\t\tdark: \"5 85% 73%\",\n\t},\n\t{\n\t\tid: \"rose\",\n\t\tlabel: \"Pink\",\n\t\ttoken: \"--basalt-accent-9\",\n\t\tlight: \"345 88% 72%\",\n\t\tdark: \"345 88% 77%\",\n\t},\n\t{\n\t\tid: \"purple\",\n\t\tlabel: \"Grape\",\n\t\ttoken: \"--basalt-accent-10\",\n\t\tlight: \"280 53% 71%\",\n\t\tdark: \"280 53% 77%\",\n\t},\n\t{\n\t\tid: \"indigo\",\n\t\tlabel: \"Blueberry\",\n\t\ttoken: \"--basalt-accent-11\",\n\t\tlight: \"237 66% 69%\",\n\t\tdark: \"237 66% 77%\",\n\t},\n\t{\n\t\tid: \"gray\",\n\t\tlabel: \"Pearl\",\n\t\ttoken: \"--basalt-accent-12\",\n\t\tlight: \"210 20% 87%\",\n\t\tdark: \"210 20% 88%\",\n\t},\n];\n\nconst LEGACY_ACCENT_IDS = new Map<string, string>([\n\t[\"jade\", \"teal\"],\n\t[\"vermilion\", \"red\"],\n\t[\"magenta\", \"rose\"],\n\t[\"orchid\", \"purple\"],\n\t[\"cobalt\", \"indigo\"],\n\t[\"steel\", \"primary\"],\n\t[\"cadet\", \"sky\"],\n\t[\"seafoam\", \"teal\"],\n\t[\"olive\", \"lime\"],\n\t[\"gold\", \"amber\"],\n\t[\"tangerine\", \"orange\"],\n\t[\"crimson\", \"red\"],\n]);\n\nexport const DEFAULT_ACCENT_ID = \"primary\";\nconst STORAGE_KEY = \"basalt-accent\";\n\ntype AccentContextValue = {\n\taccent: string;\n\tsetAccent: (id: string) => void;\n\tswatches: readonly AccentSwatch[];\n};\n\nconst AccentContext = createContext<AccentContextValue | null>(null);\n\nexport function accentSwatchById(id: string | null | undefined): AccentSwatch {\n\tconst normalized = LEGACY_ACCENT_IDS.get(id ?? \"\") ?? id;\n\treturn ACCENT_SWATCHES.find((swatch) => swatch.id === normalized) ?? ACCENT_SWATCHES[0];\n}\n\nfunction channel(c: number) {\n\treturn c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n}\n\nfunction parseHslChannels(hsl: string): [number, number, number] {\n\tconst [hue, sat, light] = hsl.trim().split(/\\s+/);\n\tconst h = Number(hue);\n\tconst s = Number(sat.replace(\"%\", \"\")) / 100;\n\tconst l = Number(light.replace(\"%\", \"\")) / 100;\n\treturn [h, s, l];\n}\n\nfunction hslToRgbChannels(h: number, s: number, l: number): [number, number, number] {\n\tconst k = (n: number) => (n + h / 30) % 12;\n\tconst a = s * Math.min(l, 1 - l);\n\tconst f = (n: number) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));\n\treturn [255 * f(0), 255 * f(8), 255 * f(4)];\n}\n\nfunction relativeLuminance(rgb: [number, number, number]): number {\n\treturn (\n\t\t0.2126 * channel(rgb[0] / 255) + 0.7152 * channel(rgb[1] / 255) + 0.0722 * channel(rgb[2] / 255)\n\t);\n}\n\nfunction wcagContrast(rgbA: [number, number, number], rgbB: [number, number, number]): number {\n\tconst lA = relativeLuminance(rgbA);\n\tconst lB = relativeLuminance(rgbB);\n\treturn (Math.max(lA, lB) + 0.05) / (Math.min(lA, lB) + 0.05);\n}\n\nconst DARK_TEXT_RGB: [number, number, number] = [26, 26, 26]; // 0 0% 10%\nconst WHITE_TEXT_RGB: [number, number, number] = [255, 255, 255]; // 0 0% 100%\n\nconst LIGHT_SURFACES_RGB: [number, number, number][] = [\n\t[238, 239, 242], // background\n\t[246, 247, 248], // card\n\t[252, 252, 253], // secondary\n\t[255, 255, 255], // bright\n];\n\nconst DARK_SURFACES_RGB: [number, number, number][] = [\n\t[23, 23, 23], // background\n\t[27, 27, 27], // card\n\t[31, 31, 31], // secondary\n\t[36, 36, 36], // bright\n];\n\nfunction compositeRgb(\n\ttop: [number, number, number, number],\n\tbottom: [number, number, number],\n): [number, number, number] {\n\treturn [\n\t\ttop[0] * top[3] + bottom[0] * (1 - top[3]),\n\t\ttop[1] * top[3] + bottom[1] * (1 - top[3]),\n\t\ttop[2] * top[3] + bottom[2] * (1 - top[3]),\n\t];\n}\n\nfunction deriveSemanticPrimary(swatch: AccentSwatch, dark: boolean): string {\n\tconst [h, s, origL] = parseHslChannels(dark ? swatch.dark : swatch.light);\n\tconst targetSurfaces = dark ? DARK_SURFACES_RGB : LIGHT_SURFACES_RGB;\n\n\tif (!dark) {\n\t\tfor (let l = Math.min(Math.round(origL * 100), 60); l >= 15; l--) {\n\t\t\tconst rgb = hslToRgbChannels(h, s, l / 100);\n\t\t\tconst minTextR = Math.min(...targetSurfaces.map((bg) => wcagContrast(rgb, bg)));\n\t\t\tif (minTextR < 4.55) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst cWhite = wcagContrast(rgb, WHITE_TEXT_RGB);\n\t\t\tif (cWhite < 4.55) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet hoverOk = true;\n\t\t\tfor (const bg of targetSurfaces) {\n\t\t\t\tconst hoverBg = compositeRgb([...rgb, 0.9], bg);\n\t\t\t\tif (wcagContrast(hoverBg, WHITE_TEXT_RGB) < 4.55) {\n\t\t\t\t\thoverOk = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hoverOk) {\n\t\t\t\treturn `${h} ${Math.round(s * 100)}% ${l}%`;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor (let l = Math.max(Math.round(origL * 100), 45); l <= 85; l++) {\n\t\t\tconst rgb = hslToRgbChannels(h, s, l / 100);\n\t\t\tconst minTextR = Math.min(...targetSurfaces.map((bg) => wcagContrast(rgb, bg)));\n\t\t\tif (minTextR < 4.55) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst cDark = wcagContrast(rgb, DARK_TEXT_RGB);\n\t\t\tif (cDark < 4.55) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet hoverOk = true;\n\t\t\tfor (const bg of targetSurfaces) {\n\t\t\t\tconst hoverBg = compositeRgb([...rgb, 0.9], bg);\n\t\t\t\tif (wcagContrast(hoverBg, DARK_TEXT_RGB) < 4.55) {\n\t\t\t\t\thoverOk = false;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hoverOk) {\n\t\t\t\treturn `${h} ${Math.round(s * 100)}% ${l}%`;\n\t\t\t}\n\t\t}\n\t}\n\treturn dark ? swatch.dark : swatch.light;\n}\n\nexport function accentForeground(hsl: string) {\n\tconst [h, s, l] = parseHslChannels(hsl);\n\tconst rgb = hslToRgbChannels(h, s, l);\n\tconst contrastWhite = wcagContrast(rgb, WHITE_TEXT_RGB);\n\tconst contrastDark = wcagContrast(rgb, DARK_TEXT_RGB);\n\treturn contrastDark >= contrastWhite ? (\"0 0% 10%\" as const) : (\"0 0% 100%\" as const);\n}\n\nexport function applyAccent(id: string, dark = false) {\n\tif (typeof document === \"undefined\") {\n\t\treturn;\n\t}\n\tapplySwatch(accentSwatchById(id), dark);\n}\n\nfunction applySwatch(swatch: AccentSwatch, dark: boolean) {\n\tconst semanticPrimary = deriveSemanticPrimary(swatch, dark);\n\tconst root = document.documentElement;\n\troot.style.setProperty(\"--basalt-primary\", semanticPrimary);\n\troot.style.setProperty(\"--basalt-primary-foreground\", accentForeground(semanticPrimary));\n\troot.style.setProperty(\"--basalt-ring\", semanticPrimary);\n\troot.dataset.accent = swatch.id;\n}\n\nexport interface AccentProviderProps {\n\t/** Color overrides for the twelve preset IDs, using HSL channels (for example `204 88% 62%`).\n\t * Invalid pairs and unknown IDs are ignored. Persistence belongs to the application.\n\t * Chart colors remain fixed. */\n\tpaletteOverrides?: Readonly<Record<string, { light: string; dark: string }>>;\n\t/**\n\t * Application components wrapped by the accent context.\n\t */\n\tchildren: ReactNode;\n\t/**\n\t * Storage key used for accent persistence.\n\t * @default \"basalt-accent\"\n\t */\n\tstorageKey?: string;\n\t/**\n\t * Initial accent identifier used when no stored preference exists or during SSR.\n\t * @default \"primary\"\n\t */\n\tdefaultAccent?: string;\n\t/**\n\t * Whether to persist accent changes to localStorage.\n\t * If false, localStorage is never read or written.\n\t * @default true\n\t */\n\tpersist?: boolean;\n\t/**\n\t * Controlled accent identifier. When provided, the provider acts as a controlled component\n\t * and internal state is driven by this prop.\n\t */\n\taccent?: string;\n\t/**\n\t * Callback fired when accent change is requested.\n\t * In controlled mode, callers are responsible for updating `accent`.\n\t */\n\tonAccentChange?: (accent: string) => void;\n\t/**\n\t * Whether to apply accent CSS variables and data-accent attribute to document.documentElement.\n\t * Set to false when a host theme system manages CSS variables directly.\n\t * @default true\n\t */\n\tapplyToDocument?: boolean;\n}\n\ninterface AccentStore {\n\tgetSnapshot: () => string;\n\tsubscribe: (listener: () => void) => () => void;\n\tsetAccent: (next: string) => void;\n\tupdateConfig: (config: { storageKey: string; defaultAccent: string; persist: boolean }) => void;\n}\n\nfunction isValidAccentId(value: unknown): value is string {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\t(ACCENT_SWATCHES.some((s) => s.id === value) || LEGACY_ACCENT_IDS.has(value))\n\t);\n}\n\ntype StorageReadResult = { status: \"success\"; value: string | null } | { status: \"error\" };\n\nfunction safeGetStorageItem(key: string): StorageReadResult {\n\ttry {\n\t\tif (typeof window === \"undefined\" || !window.localStorage) {\n\t\t\treturn { status: \"error\" };\n\t\t}\n\t\tconst value = window.localStorage.getItem(key);\n\t\treturn { status: \"success\", value };\n\t} catch {\n\t\treturn { status: \"error\" };\n\t}\n}\n\nfunction safeSetStorageItem(key: string, value: string): boolean {\n\ttry {\n\t\tif (typeof window === \"undefined\" || !window.localStorage) {\n\t\t\treturn false;\n\t\t}\n\t\twindow.localStorage.setItem(key, value);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction isLocalStorageArea(area: Storage | null | undefined): boolean {\n\tif (!area) {\n\t\treturn true;\n\t}\n\ttry {\n\t\tif (typeof window !== \"undefined\" && window.localStorage) {\n\t\t\treturn area === window.localStorage;\n\t\t}\n\t} catch {\n\t\treturn false;\n\t}\n\treturn false;\n}\n\nconst ACCENT_CHANGE_EVENT = \"basalt:accent-change\";\n\ninterface AccentChangeEventDetail {\n\tkey: string;\n\tvalue: string;\n\twriteSucceeded: boolean;\n}\n\nfunction createAccentStore(\n\tinitialStorageKey: string,\n\tinitialDefaultAccent: string,\n\tinitialPersist: boolean,\n): AccentStore {\n\tlet storageKey = initialStorageKey;\n\tlet defaultAccent = accentSwatchById(initialDefaultAccent).id;\n\tlet persist = initialPersist;\n\n\tlet memoryAccent: string = defaultAccent;\n\tlet hasExplicitSelection = false;\n\tlet lastSetFailed = false;\n\n\tif (persist) {\n\t\tconst res = safeGetStorageItem(storageKey);\n\t\tif (res.status === \"success\" && isValidAccentId(res.value)) {\n\t\t\tmemoryAccent = accentSwatchById(res.value).id;\n\t\t\thasExplicitSelection = true;\n\t\t}\n\t}\n\n\tconst listeners = new Set<() => void>();\n\n\tconst notify = () => {\n\t\tfor (const listener of listeners) {\n\t\t\tlistener();\n\t\t}\n\t};\n\n\tconst onInternalChange = (event: Event) => {\n\t\tif (!persist) {\n\t\t\treturn;\n\t\t}\n\t\tconst customEv = event as CustomEvent<AccentChangeEventDetail>;\n\t\tif (!customEv.detail || customEv.detail.key !== storageKey) {\n\t\t\treturn;\n\t\t}\n\t\tconst { value, writeSucceeded } = customEv.detail;\n\t\tif (writeSucceeded) {\n\t\t\tlastSetFailed = false;\n\t\t} else {\n\t\t\tlastSetFailed = true;\n\t\t}\n\t\tmemoryAccent = value;\n\t\thasExplicitSelection = true;\n\t\tnotify();\n\t};\n\n\tconst onStorage = (event: StorageEvent | Event) => {\n\t\tif (!persist) {\n\t\t\treturn;\n\t\t}\n\t\tconst storageEv = event as Partial<StorageEvent>;\n\t\tif (\"key\" in storageEv && storageEv.key !== undefined) {\n\t\t\tif (!isLocalStorageArea(storageEv.storageArea)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (storageEv.key !== null && storageEv.key !== storageKey) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlastSetFailed = false;\n\t\t\tconst rawVal = storageEv.newValue;\n\t\t\tif (rawVal === null || rawVal === undefined || !isValidAccentId(rawVal)) {\n\t\t\t\tmemoryAccent = defaultAccent;\n\t\t\t\thasExplicitSelection = false;\n\t\t\t\tnotify();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tmemoryAccent = accentSwatchById(rawVal).id;\n\t\t\thasExplicitSelection = true;\n\t\t\tnotify();\n\t\t\treturn;\n\t\t}\n\t\tif (lastSetFailed) {\n\t\t\treturn;\n\t\t}\n\t\tconst res = safeGetStorageItem(storageKey);\n\t\tif (res.status === \"error\") {\n\t\t\t// Read failed: preserve current cached memory accent, do not revert to default\n\t\t\treturn;\n\t\t}\n\t\tif (isValidAccentId(res.value)) {\n\t\t\tmemoryAccent = accentSwatchById(res.value).id;\n\t\t\thasExplicitSelection = true;\n\t\t\tnotify();\n\t\t} else {\n\t\t\t// Key removed or invalid value stored: revert to default\n\t\t\tmemoryAccent = defaultAccent;\n\t\t\thasExplicitSelection = false;\n\t\t\tnotify();\n\t\t}\n\t};\n\n\tlet cleanupStorageListener: (() => void) | null = null;\n\tconst attachStorageListener = () => {\n\t\tif (typeof window === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\t\tif (listeners.size === 1 && !cleanupStorageListener) {\n\t\t\twindow.addEventListener(\"storage\", onStorage);\n\t\t\twindow.addEventListener(ACCENT_CHANGE_EVENT, onInternalChange);\n\t\t\tcleanupStorageListener = () => {\n\t\t\t\twindow.removeEventListener(\"storage\", onStorage);\n\t\t\t\twindow.removeEventListener(ACCENT_CHANGE_EVENT, onInternalChange);\n\t\t\t\tcleanupStorageListener = null;\n\t\t\t};\n\t\t}\n\t};\n\n\tconst detachStorageListener = () => {\n\t\tif (listeners.size === 0 && cleanupStorageListener) {\n\t\t\tcleanupStorageListener();\n\t\t}\n\t};\n\n\treturn {\n\t\tgetSnapshot: () => memoryAccent,\n\t\tsubscribe: (listener: () => void) => {\n\t\t\tlisteners.add(listener);\n\t\t\tattachStorageListener();\n\t\t\treturn () => {\n\t\t\t\tlisteners.delete(listener);\n\t\t\t\tdetachStorageListener();\n\t\t\t};\n\t\t},\n\t\tsetAccent: (next: string) => {\n\t\t\tconst validId = accentSwatchById(next).id;\n\t\t\tmemoryAccent = validId;\n\t\t\thasExplicitSelection = true;\n\t\t\tlet writeSucceeded = true;\n\t\t\tif (persist) {\n\t\t\t\tconst success = safeSetStorageItem(storageKey, validId);\n\t\t\t\tlastSetFailed = !success;\n\t\t\t\twriteSucceeded = success;\n\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\twindow.dispatchEvent(\n\t\t\t\t\t\t\tnew CustomEvent<AccentChangeEventDetail>(ACCENT_CHANGE_EVENT, {\n\t\t\t\t\t\t\t\tdetail: { key: storageKey, value: validId, writeSucceeded },\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tnotify();\n\t\t},\n\t\tupdateConfig: (config) => {\n\t\t\tconst keyChanged = storageKey !== config.storageKey;\n\t\t\tconst persistChanged = persist !== config.persist;\n\t\t\tconst normalizedDefault = accentSwatchById(config.defaultAccent).id;\n\t\t\tconst defaultChanged = defaultAccent !== normalizedDefault;\n\n\t\t\tconst oldPersist = persist;\n\t\t\tstorageKey = config.storageKey;\n\t\t\tdefaultAccent = normalizedDefault;\n\t\t\tpersist = config.persist;\n\n\t\t\tif (keyChanged) {\n\t\t\t\tif (persist) {\n\t\t\t\t\tconst res = safeGetStorageItem(storageKey);\n\t\t\t\t\tif (res.status === \"success\") {\n\t\t\t\t\t\tlastSetFailed = false;\n\t\t\t\t\t\tif (isValidAccentId(res.value)) {\n\t\t\t\t\t\t\tmemoryAccent = accentSwatchById(res.value).id;\n\t\t\t\t\t\t\thasExplicitSelection = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tmemoryAccent = defaultAccent;\n\t\t\t\t\t\t\thasExplicitSelection = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tnotify();\n\t\t\t\t}\n\t\t\t} else if (persistChanged) {\n\t\t\t\tif (!oldPersist && persist) {\n\t\t\t\t\tconst res = safeGetStorageItem(storageKey);\n\t\t\t\t\tif (res.status === \"success\") {\n\t\t\t\t\t\tlastSetFailed = false;\n\t\t\t\t\t\tif (isValidAccentId(res.value)) {\n\t\t\t\t\t\t\tmemoryAccent = accentSwatchById(res.value).id;\n\t\t\t\t\t\t\thasExplicitSelection = true;\n\t\t\t\t\t\t\tnotify();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (defaultChanged) {\n\t\t\t\tif (!hasExplicitSelection) {\n\t\t\t\t\tif (persist) {\n\t\t\t\t\t\tconst res = safeGetStorageItem(storageKey);\n\t\t\t\t\t\tif (res.status === \"success\" && !isValidAccentId(res.value)) {\n\t\t\t\t\t\t\tmemoryAccent = defaultAccent;\n\t\t\t\t\t\t\tnotify();\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmemoryAccent = defaultAccent;\n\t\t\t\t\t\tnotify();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction validHsl(value: unknown): value is string {\n\tif (typeof value !== \"string\" || !/^\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?%\\s+\\d+(?:\\.\\d+)?%$/.test(value))\n\t\treturn false;\n\tconst [h, s, l] = parseHslChannels(value);\n\treturn h <= 360 && s <= 1 && l <= 1;\n}\n\nfunction isDarkMode(): boolean {\n\tif (typeof document === \"undefined\") {\n\t\treturn false;\n\t}\n\treturn document.documentElement.classList.contains(\"dark\");\n}\n\nexport function AccentProvider({\n\tchildren,\n\tpaletteOverrides,\n\tstorageKey = STORAGE_KEY,\n\tdefaultAccent = DEFAULT_ACCENT_ID,\n\tpersist = true,\n\taccent: controlledAccent,\n\tonAccentChange,\n\tapplyToDocument = true,\n}: AccentProviderProps) {\n\tconst isControlled = controlledAccent !== undefined;\n\tconst swatches = useMemo(\n\t\t() =>\n\t\t\tACCENT_SWATCHES.map((swatch) => {\n\t\t\t\tconst override = paletteOverrides?.[swatch.id];\n\t\t\t\treturn override && validHsl(override.light) && validHsl(override.dark)\n\t\t\t\t\t? { ...swatch, light: override.light, dark: override.dark }\n\t\t\t\t\t: swatch;\n\t\t\t}),\n\t\t[paletteOverrides],\n\t);\n\n\tconst [store] = useState(() => createAccentStore(storageKey, defaultAccent, persist));\n\n\tuseEffect(() => {\n\t\tstore.updateConfig({ storageKey, defaultAccent, persist });\n\t}, [store, storageKey, defaultAccent, persist]);\n\n\tconst getServerSnapshot = useCallback(() => accentSwatchById(defaultAccent).id, [defaultAccent]);\n\n\tconst storeAccent = useSyncExternalStore(store.subscribe, store.getSnapshot, getServerSnapshot);\n\n\tconst currentAccent = isControlled ? accentSwatchById(controlledAccent).id : storeAccent;\n\n\tuseEffect(() => {\n\t\tif (!applyToDocument || typeof document === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\t\tconst apply = () => {\n\t\t\tconst dark = isDarkMode();\n\t\t\tfor (const swatch of swatches)\n\t\t\t\tdocument.documentElement.style.setProperty(swatch.token, dark ? swatch.dark : swatch.light);\n\t\t\tapplySwatch(swatches.find((swatch) => swatch.id === currentAccent) ?? swatches[0], dark);\n\t\t};\n\t\tapply();\n\t\tconst observer = new MutationObserver(apply);\n\t\tobserver.observe(document.documentElement, { attributes: true, attributeFilter: [\"class\"] });\n\t\treturn () => observer.disconnect();\n\t}, [currentAccent, applyToDocument, swatches]);\n\n\tconst setAccent = useCallback(\n\t\t(next: string) => {\n\t\t\tconst validId = accentSwatchById(next).id;\n\t\t\tif (isControlled) {\n\t\t\t\tonAccentChange?.(validId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstore.setAccent(validId);\n\t\t\tonAccentChange?.(validId);\n\t\t},\n\t\t[isControlled, onAccentChange, store],\n\t);\n\n\tconst value = useMemo(\n\t\t() => ({ accent: currentAccent, setAccent, swatches }),\n\t\t[currentAccent, setAccent, swatches],\n\t);\n\treturn <AccentContext.Provider value={value}>{children}</AccentContext.Provider>;\n}\n\nexport function useAccent() {\n\tconst ctx = useContext(AccentContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useAccent must be used within AccentProvider\");\n\t}\n\treturn ctx;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"accent.js","names":[],"sources":["../../src/providers/accent.tsx"],"sourcesContent":["import {\n\tcreateContext,\n\ttype ReactNode,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseMemo,\n\tuseState,\n\tuseSyncExternalStore,\n} from \"react\";\nimport { createPreferenceStore } from \"../utils/preference-store\";\n\nexport type AccentSwatch = {\n\tid: string;\n\tlabel: string;\n\ttoken: string;\n\tlight: string;\n\tdark: string;\n};\n\n/** Twelve candy accents inspired by the translucent iMac and iPhone 5C finishes. */\nexport const ACCENT_SWATCHES: readonly AccentSwatch[] = [\n\t{\n\t\tid: \"primary\",\n\t\tlabel: \"Blue\",\n\t\ttoken: \"--basalt-accent-1\",\n\t\tlight: \"204 88% 62%\",\n\t\tdark: \"204 90% 70%\",\n\t},\n\t{\n\t\tid: \"sky\",\n\t\tlabel: \"Ice\",\n\t\ttoken: \"--basalt-accent-2\",\n\t\tlight: \"191 79% 70%\",\n\t\tdark: \"191 79% 74%\",\n\t},\n\t{\n\t\tid: \"teal\",\n\t\tlabel: \"Bondi\",\n\t\ttoken: \"--basalt-accent-3\",\n\t\tlight: \"182 62% 47%\",\n\t\tdark: \"182 62% 63%\",\n\t},\n\t{\n\t\tid: \"green\",\n\t\tlabel: \"Green\",\n\t\ttoken: \"--basalt-accent-4\",\n\t\tlight: \"113 58% 62%\",\n\t\tdark: \"113 58% 70%\",\n\t},\n\t{\n\t\tid: \"lime\",\n\t\tlabel: \"Lime\",\n\t\ttoken: \"--basalt-accent-5\",\n\t\tlight: \"79 70% 64%\",\n\t\tdark: \"79 70% 70%\",\n\t},\n\t{\n\t\tid: \"amber\",\n\t\tlabel: \"Yellow\",\n\t\ttoken: \"--basalt-accent-6\",\n\t\tlight: \"49 100% 69%\",\n\t\tdark: \"49 100% 73%\",\n\t},\n\t{\n\t\tid: \"orange\",\n\t\tlabel: \"Tangerine\",\n\t\ttoken: \"--basalt-accent-7\",\n\t\tlight: \"27 95% 65%\",\n\t\tdark: \"27 95% 72%\",\n\t},\n\t{\n\t\tid: \"red\",\n\t\tlabel: \"Strawberry\",\n\t\ttoken: \"--basalt-accent-8\",\n\t\tlight: \"5 85% 66%\",\n\t\tdark: \"5 85% 73%\",\n\t},\n\t{\n\t\tid: \"rose\",\n\t\tlabel: \"Pink\",\n\t\ttoken: \"--basalt-accent-9\",\n\t\tlight: \"345 88% 72%\",\n\t\tdark: \"345 88% 77%\",\n\t},\n\t{\n\t\tid: \"purple\",\n\t\tlabel: \"Grape\",\n\t\ttoken: \"--basalt-accent-10\",\n\t\tlight: \"280 53% 71%\",\n\t\tdark: \"280 53% 77%\",\n\t},\n\t{\n\t\tid: \"indigo\",\n\t\tlabel: \"Blueberry\",\n\t\ttoken: \"--basalt-accent-11\",\n\t\tlight: \"237 66% 69%\",\n\t\tdark: \"237 66% 77%\",\n\t},\n\t{\n\t\tid: \"gray\",\n\t\tlabel: \"Pearl\",\n\t\ttoken: \"--basalt-accent-12\",\n\t\tlight: \"210 20% 87%\",\n\t\tdark: \"210 20% 88%\",\n\t},\n];\n\nconst LEGACY_ACCENT_IDS = new Map<string, string>([\n\t[\"jade\", \"teal\"],\n\t[\"vermilion\", \"red\"],\n\t[\"magenta\", \"rose\"],\n\t[\"orchid\", \"purple\"],\n\t[\"cobalt\", \"indigo\"],\n\t[\"steel\", \"primary\"],\n\t[\"cadet\", \"sky\"],\n\t[\"seafoam\", \"teal\"],\n\t[\"olive\", \"lime\"],\n\t[\"gold\", \"amber\"],\n\t[\"tangerine\", \"orange\"],\n\t[\"crimson\", \"red\"],\n]);\n\nexport const DEFAULT_ACCENT_ID = \"primary\";\nconst STORAGE_KEY = \"basalt-accent\";\n\ntype AccentContextValue = {\n\taccent: string;\n\tsetAccent: (id: string) => void;\n\tswatches: readonly AccentSwatch[];\n};\n\nconst AccentContext = createContext<AccentContextValue | null>(null);\n\nexport function accentSwatchById(id: string | null | undefined): AccentSwatch {\n\tconst normalized = LEGACY_ACCENT_IDS.get(id ?? \"\") ?? id;\n\treturn ACCENT_SWATCHES.find((swatch) => swatch.id === normalized) ?? ACCENT_SWATCHES[0];\n}\n\nfunction channel(c: number) {\n\treturn c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n}\n\nfunction parseHslChannels(hsl: string): [number, number, number] {\n\tconst [hue, sat, light] = hsl.trim().split(/\\s+/);\n\tconst h = Number(hue);\n\tconst s = Number(sat.replace(\"%\", \"\")) / 100;\n\tconst l = Number(light.replace(\"%\", \"\")) / 100;\n\treturn [h, s, l];\n}\n\nfunction hslToRgbChannels(h: number, s: number, l: number): [number, number, number] {\n\tconst k = (n: number) => (n + h / 30) % 12;\n\tconst a = s * Math.min(l, 1 - l);\n\tconst f = (n: number) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));\n\treturn [255 * f(0), 255 * f(8), 255 * f(4)];\n}\n\nfunction relativeLuminance(rgb: [number, number, number]): number {\n\treturn (\n\t\t0.2126 * channel(rgb[0] / 255) + 0.7152 * channel(rgb[1] / 255) + 0.0722 * channel(rgb[2] / 255)\n\t);\n}\n\nfunction wcagContrast(rgbA: [number, number, number], rgbB: [number, number, number]): number {\n\tconst lA = relativeLuminance(rgbA);\n\tconst lB = relativeLuminance(rgbB);\n\treturn (Math.max(lA, lB) + 0.05) / (Math.min(lA, lB) + 0.05);\n}\n\nconst DARK_TEXT_RGB: [number, number, number] = [26, 26, 26]; // 0 0% 10%\nconst WHITE_TEXT_RGB: [number, number, number] = [255, 255, 255]; // 0 0% 100%\n\nconst LIGHT_SURFACES_RGB: [number, number, number][] = [\n\t[238, 239, 242], // background\n\t[246, 247, 248], // card\n\t[252, 252, 253], // secondary\n\t[255, 255, 255], // bright\n];\n\nconst DARK_SURFACES_RGB: [number, number, number][] = [\n\t[23, 23, 23], // background\n\t[27, 27, 27], // card\n\t[31, 31, 31], // secondary\n\t[36, 36, 36], // bright\n];\n\nfunction compositeRgb(\n\ttop: [number, number, number, number],\n\tbottom: [number, number, number],\n): [number, number, number] {\n\treturn [\n\t\ttop[0] * top[3] + bottom[0] * (1 - top[3]),\n\t\ttop[1] * top[3] + bottom[1] * (1 - top[3]),\n\t\ttop[2] * top[3] + bottom[2] * (1 - top[3]),\n\t];\n}\n\nfunction deriveSemanticPrimary(swatch: AccentSwatch, dark: boolean): string {\n\tconst [h, s, origL] = parseHslChannels(dark ? swatch.dark : swatch.light);\n\tconst targetSurfaces = dark ? DARK_SURFACES_RGB : LIGHT_SURFACES_RGB;\n\tconst foreground = dark ? DARK_TEXT_RGB : WHITE_TEXT_RGB;\n\tconst start = dark\n\t\t? Math.max(Math.round(origL * 100), 45)\n\t\t: Math.min(Math.round(origL * 100), 60);\n\n\tfor (let l = start; dark ? l <= 85 : l >= 15; l += dark ? 1 : -1) {\n\t\tconst rgb = hslToRgbChannels(h, s, l / 100);\n\t\tconst minTextR = Math.min(...targetSurfaces.map((bg) => wcagContrast(rgb, bg)));\n\t\tif (minTextR < 4.55) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (wcagContrast(rgb, foreground) < 4.55) {\n\t\t\tcontinue;\n\t\t}\n\t\tlet hoverOk = true;\n\t\tfor (const bg of targetSurfaces) {\n\t\t\tconst hoverBg = compositeRgb([...rgb, 0.9], bg);\n\t\t\tif (wcagContrast(hoverBg, foreground) < 4.55) {\n\t\t\t\thoverOk = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (hoverOk) {\n\t\t\treturn `${h} ${Math.round(s * 100)}% ${l}%`;\n\t\t}\n\t}\n\treturn dark ? swatch.dark : swatch.light;\n}\n\nexport function accentForeground(hsl: string) {\n\tconst [h, s, l] = parseHslChannels(hsl);\n\tconst rgb = hslToRgbChannels(h, s, l);\n\tconst contrastWhite = wcagContrast(rgb, WHITE_TEXT_RGB);\n\tconst contrastDark = wcagContrast(rgb, DARK_TEXT_RGB);\n\treturn contrastDark >= contrastWhite ? (\"0 0% 10%\" as const) : (\"0 0% 100%\" as const);\n}\n\nexport function applyAccent(id: string, dark = false) {\n\tif (typeof document === \"undefined\") {\n\t\treturn;\n\t}\n\tapplySwatch(accentSwatchById(id), dark);\n}\n\nfunction applySwatch(swatch: AccentSwatch, dark: boolean) {\n\tconst semanticPrimary = deriveSemanticPrimary(swatch, dark);\n\tconst root = document.documentElement;\n\troot.style.setProperty(\"--basalt-primary\", semanticPrimary);\n\troot.style.setProperty(\"--basalt-primary-foreground\", accentForeground(semanticPrimary));\n\troot.style.setProperty(\"--basalt-ring\", semanticPrimary);\n\troot.dataset.accent = swatch.id;\n}\n\nexport interface AccentProviderProps {\n\t/** Color overrides for the twelve preset IDs, using HSL channels (for example `204 88% 62%`).\n\t * Invalid pairs and unknown IDs are ignored. Persistence belongs to the application.\n\t * Chart colors remain fixed. */\n\tpaletteOverrides?: Readonly<Record<string, { light: string; dark: string }>>;\n\t/**\n\t * Application components wrapped by the accent context.\n\t */\n\tchildren: ReactNode;\n\t/**\n\t * Storage key used for accent persistence.\n\t * @default \"basalt-accent\"\n\t */\n\tstorageKey?: string;\n\t/**\n\t * Initial accent identifier used when no stored preference exists or during SSR.\n\t * @default \"primary\"\n\t */\n\tdefaultAccent?: string;\n\t/**\n\t * Whether to persist accent changes to localStorage.\n\t * If false, localStorage is never read or written.\n\t * @default true\n\t */\n\tpersist?: boolean;\n\t/**\n\t * Controlled accent identifier. When provided, the provider acts as a controlled component\n\t * and internal state is driven by this prop.\n\t */\n\taccent?: string;\n\t/**\n\t * Callback fired when accent change is requested.\n\t * In controlled mode, callers are responsible for updating `accent`.\n\t */\n\tonAccentChange?: (accent: string) => void;\n\t/**\n\t * Whether to apply accent CSS variables and data-accent attribute to document.documentElement.\n\t * Set to false when a host theme system manages CSS variables directly.\n\t * @default true\n\t */\n\tapplyToDocument?: boolean;\n}\n\nfunction isValidAccentId(value: unknown): value is string {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\t(ACCENT_SWATCHES.some((s) => s.id === value) || LEGACY_ACCENT_IDS.has(value))\n\t);\n}\n\nfunction validHsl(value: unknown): value is string {\n\tif (typeof value !== \"string\" || !/^\\d+(?:\\.\\d+)?\\s+\\d+(?:\\.\\d+)?%\\s+\\d+(?:\\.\\d+)?%$/.test(value))\n\t\treturn false;\n\tconst [h, s, l] = parseHslChannels(value);\n\treturn h <= 360 && s <= 1 && l <= 1;\n}\n\nfunction isDarkMode(): boolean {\n\tif (typeof document === \"undefined\") {\n\t\treturn false;\n\t}\n\treturn document.documentElement.classList.contains(\"dark\");\n}\n\nexport function AccentProvider({\n\tchildren,\n\tpaletteOverrides,\n\tstorageKey = STORAGE_KEY,\n\tdefaultAccent = DEFAULT_ACCENT_ID,\n\tpersist = true,\n\taccent: controlledAccent,\n\tonAccentChange,\n\tapplyToDocument = true,\n}: AccentProviderProps) {\n\tconst isControlled = controlledAccent !== undefined;\n\tconst swatches = useMemo(\n\t\t() =>\n\t\t\tACCENT_SWATCHES.map((swatch) => {\n\t\t\t\tconst override = paletteOverrides?.[swatch.id];\n\t\t\t\treturn override && validHsl(override.light) && validHsl(override.dark)\n\t\t\t\t\t? { ...swatch, light: override.light, dark: override.dark }\n\t\t\t\t\t: swatch;\n\t\t\t}),\n\t\t[paletteOverrides],\n\t);\n\n\tconst [store] = useState(() =>\n\t\tcreatePreferenceStore({\n\t\t\tstorageKey,\n\t\t\tdefaultValue: defaultAccent,\n\t\t\tpersist,\n\t\t\tisValid: isValidAccentId,\n\t\t\tnormalize: (value) => accentSwatchById(value).id,\n\t\t\teventName: \"basalt:accent-change\",\n\t\t}),\n\t);\n\n\tuseEffect(() => {\n\t\tstore.updateConfig({ storageKey, defaultValue: defaultAccent, persist });\n\t}, [store, storageKey, defaultAccent, persist]);\n\n\tconst getServerSnapshot = useCallback(() => accentSwatchById(defaultAccent).id, [defaultAccent]);\n\n\tconst storeAccent = useSyncExternalStore(store.subscribe, store.getSnapshot, getServerSnapshot);\n\n\tconst currentAccent = isControlled ? accentSwatchById(controlledAccent).id : storeAccent;\n\n\tuseEffect(() => {\n\t\tif (!applyToDocument || typeof document === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\t\tconst apply = () => {\n\t\t\tconst dark = isDarkMode();\n\t\t\tfor (const swatch of swatches)\n\t\t\t\tdocument.documentElement.style.setProperty(swatch.token, dark ? swatch.dark : swatch.light);\n\t\t\tapplySwatch(swatches.find((swatch) => swatch.id === currentAccent) ?? swatches[0], dark);\n\t\t};\n\t\tapply();\n\t\tconst observer = new MutationObserver(apply);\n\t\tobserver.observe(document.documentElement, { attributes: true, attributeFilter: [\"class\"] });\n\t\treturn () => observer.disconnect();\n\t}, [currentAccent, applyToDocument, swatches]);\n\n\tconst setAccent = useCallback(\n\t\t(next: string) => {\n\t\t\tconst validId = accentSwatchById(next).id;\n\t\t\tif (isControlled) {\n\t\t\t\tonAccentChange?.(validId);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstore.setValue(validId);\n\t\t\tonAccentChange?.(validId);\n\t\t},\n\t\t[isControlled, onAccentChange, store],\n\t);\n\n\tconst value = useMemo(\n\t\t() => ({ accent: currentAccent, setAccent, swatches }),\n\t\t[currentAccent, setAccent, swatches],\n\t);\n\treturn <AccentContext.Provider value={value}>{children}</AccentContext.Provider>;\n}\n\nexport function useAccent() {\n\tconst ctx = useContext(AccentContext);\n\tif (!ctx) {\n\t\tthrow new Error(\"useAccent must be used within AccentProvider\");\n\t}\n\treturn ctx;\n}\n"],"mappings":"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"}
|