@stll/ui 0.25.2 → 0.26.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/dist/components/button-variants.d.ts +1 -1
- package/dist/components/color-picker.d.ts +15 -5
- package/dist/components/color-picker.js +114 -47
- package/dist/components/input-group.d.ts +1 -1
- package/dist/components/sidebar.d.ts +2 -2
- package/dist/inspector/tabs.d.ts +1 -1
- package/dist/lib/control-size.d.ts +1 -1
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
declare const buttonAccessibleDisabledClass = "cursor-not-allowed opacity-64";
|
|
12
12
|
declare const buttonVariants: (props?: ({
|
|
13
|
-
size?: "default" | "
|
|
13
|
+
size?: "default" | "sm" | "lg" | "chip" | "icon" | "icon-lg" | "icon-sm" | "icon-xl" | "icon-xs" | "xl" | "xs" | null | undefined;
|
|
14
14
|
variant?: "link" | "default" | "destructive" | "destructive-outline" | "ghost" | "outline" | "secondary" | null | undefined;
|
|
15
15
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
16
16
|
//#endregion
|
|
@@ -31,17 +31,27 @@ type ColorPickerProps = {
|
|
|
31
31
|
align?: "start" | "center" | "end";
|
|
32
32
|
className?: string;
|
|
33
33
|
};
|
|
34
|
-
type
|
|
34
|
+
type ColorPickerContentBaseProps = {
|
|
35
35
|
value?: string | undefined;
|
|
36
36
|
onSelect?: ((value: string) => void) | undefined;
|
|
37
|
-
onClear?: (() => void) | undefined;
|
|
38
37
|
presets: ColorPreset[];
|
|
39
|
-
columns: number;
|
|
40
|
-
defaultExpanded: boolean;
|
|
41
38
|
moreLabel: string;
|
|
42
39
|
};
|
|
40
|
+
type ColorPickerContentProps = ColorPickerContentBaseProps & ({
|
|
41
|
+
columns: number;
|
|
42
|
+
defaultExpanded: boolean;
|
|
43
|
+
onClear?: (() => void) | undefined;
|
|
44
|
+
/** Popover content closes on preset selection. */
|
|
45
|
+
presentation?: "popover";
|
|
46
|
+
} | {
|
|
47
|
+
columns?: never;
|
|
48
|
+
defaultExpanded?: never;
|
|
49
|
+
onClear?: never;
|
|
50
|
+
/** Inline content stays mounted and reserves its popup for custom color. */
|
|
51
|
+
presentation: "inline";
|
|
52
|
+
});
|
|
43
53
|
declare const DEFAULT_PRESETS: ColorPreset[];
|
|
44
|
-
declare const ColorPickerContent: ({ value, onSelect, onClear, presets, columns, defaultExpanded, moreLabel }: ColorPickerContentProps) => React$1.JSX.Element;
|
|
54
|
+
declare const ColorPickerContent: ({ value, onSelect, onClear, presets, columns, defaultExpanded, moreLabel, presentation }: ColorPickerContentProps) => React$1.JSX.Element;
|
|
45
55
|
declare const ColorPicker: ({ value, onSelect, onClear, presets, columns, defaultExpanded, moreLabel, children, side, align, className }: ColorPickerProps) => React$1.JSX.Element;
|
|
46
56
|
//#endregion
|
|
47
57
|
export { ColorPicker, ColorPickerContent, type ColorPickerContentProps, type ColorPickerProps, type ColorPreset, DEFAULT_PRESETS };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { OVERLAY_LAYER_CLASS_NAMES } from "../lib/overlay-layer.js";
|
|
3
4
|
import { CheckIcon, ChevronDownIcon } from "lucide-react";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
import { Suspense, lazy, useState } from "react";
|
|
6
7
|
import { Popover } from "@base-ui/react/popover";
|
|
7
8
|
//#region src/components/color-picker.tsx
|
|
@@ -112,25 +113,97 @@ const isLightHex = (hex) => {
|
|
|
112
113
|
const b = Number.parseInt(hex.slice(4, 6), 16);
|
|
113
114
|
return (r * 299 + g * 587 + b * 114) / 1e3 > 220;
|
|
114
115
|
};
|
|
116
|
+
const checkIconColorClassNames = {
|
|
117
|
+
dark: "text-(--color-white)",
|
|
118
|
+
light: "text-(--color-black)"
|
|
119
|
+
};
|
|
115
120
|
/** Check if a value looks like a 6-char hex (no CSS vars, no named colors). */
|
|
116
121
|
const looksLikeHex = (v) => /^[0-9A-Fa-f]{6}$/u.test(v);
|
|
117
|
-
const ColorSwatch = ({ cssColor, selected, label, isLight, onClick }) =>
|
|
118
|
-
|
|
122
|
+
const ColorSwatch = ({ cssColor, selected, label, isLight, onClick, presentation }) => {
|
|
123
|
+
let selectionClassName = "border-border/40";
|
|
124
|
+
if (selected) selectionClassName = presentation === "inline" ? "border-transparent ring-2 ring-ring" : "border-foreground ring-ring/24 ring-1";
|
|
125
|
+
const swatch = /* @__PURE__ */ jsx("button", {
|
|
119
126
|
"aria-label": label,
|
|
120
|
-
|
|
127
|
+
"aria-pressed": selected,
|
|
128
|
+
className: cn(presentation === "inline" ? "ring-offset-popover relative grid size-11 shrink-0 place-items-center rounded-full border ring-offset-2 transition-transform outline-none hover:scale-105 focus-visible:ring-2" : "hover:border-foreground relative flex size-6 items-center justify-center rounded-md border transition-[transform,border-color] hover:scale-115 sm:size-5", selectionClassName, isLight && !selected && "border-border"),
|
|
121
129
|
onClick,
|
|
122
130
|
style: { backgroundColor: cssColor },
|
|
123
|
-
type: "button"
|
|
131
|
+
type: "button",
|
|
132
|
+
children: selected && /* @__PURE__ */ jsx(CheckIcon, { className: cn("pointer-events-none", presentation === "inline" ? "bg-background/88 text-foreground size-5 rounded-full p-0.5 shadow-sm" : "size-3 sm:size-2.5", presentation === "popover" && checkIconColorClassNames[isLight ? "light" : "dark"]) })
|
|
133
|
+
});
|
|
134
|
+
return presentation === "inline" ? swatch : /* @__PURE__ */ jsx(Popover.Close, { render: swatch });
|
|
135
|
+
};
|
|
136
|
+
const CustomColorControls = ({ handleInputChange, handlePickerChange, inputHex, pickerHex }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Suspense, {
|
|
137
|
+
fallback: /* @__PURE__ */ jsx("div", {
|
|
138
|
+
"aria-hidden": true,
|
|
139
|
+
className: "ring-border/30 h-[140px] w-full rounded-lg ring-1"
|
|
124
140
|
}),
|
|
125
|
-
children:
|
|
126
|
-
className: "
|
|
127
|
-
|
|
141
|
+
children: /* @__PURE__ */ jsx(HexColorPicker, {
|
|
142
|
+
className: "ring-border/30 !h-[140px] !w-full overflow-hidden rounded-lg ring-1",
|
|
143
|
+
color: pickerHex,
|
|
144
|
+
onChange: (hex) => handlePickerChange(hex.replace("#", ""))
|
|
128
145
|
})
|
|
129
|
-
})
|
|
130
|
-
|
|
146
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
147
|
+
className: "flex items-center gap-1.5",
|
|
148
|
+
children: [
|
|
149
|
+
/* @__PURE__ */ jsx("span", {
|
|
150
|
+
className: "text-muted-foreground text-[11px]",
|
|
151
|
+
children: "#"
|
|
152
|
+
}),
|
|
153
|
+
/* @__PURE__ */ jsx("input", {
|
|
154
|
+
"aria-label": "Custom hex color",
|
|
155
|
+
className: "border-input bg-background text-foreground h-6 flex-1 rounded border px-1.5 font-mono text-[11px] outline-none",
|
|
156
|
+
dir: "ltr",
|
|
157
|
+
maxLength: 6,
|
|
158
|
+
onChange: (event) => handleInputChange(event.target.value),
|
|
159
|
+
onKeyDown: (event) => {
|
|
160
|
+
if (event.key !== "Escape") event.stopPropagation();
|
|
161
|
+
},
|
|
162
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
163
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
164
|
+
placeholder: "FF0000",
|
|
165
|
+
value: inputHex
|
|
166
|
+
}),
|
|
167
|
+
isValidHex(inputHex) && /* @__PURE__ */ jsx("span", {
|
|
168
|
+
className: "border-border size-6 shrink-0 rounded border",
|
|
169
|
+
style: { backgroundColor: `#${inputHex}` }
|
|
170
|
+
})
|
|
171
|
+
]
|
|
172
|
+
})] });
|
|
173
|
+
const InlineCustomColor = ({ customSelected, handleInputChange, handlePickerChange, inputHex, label, pickerHex, presets, value }) => {
|
|
174
|
+
const customColor = customSelected ? `#${value}` : void 0;
|
|
175
|
+
const customGradient = `conic-gradient(${presets.map((preset) => swatchColor(preset)).join(", ")})`;
|
|
176
|
+
return /* @__PURE__ */ jsxs(Popover.Root, { children: [/* @__PURE__ */ jsx(Popover.Trigger, {
|
|
177
|
+
render: /* @__PURE__ */ jsx("button", {
|
|
178
|
+
"aria-label": label,
|
|
179
|
+
"aria-pressed": customSelected,
|
|
180
|
+
className: cn("ring-offset-popover relative grid size-11 shrink-0 place-items-center rounded-full border border-transparent ring-offset-2 transition-transform outline-none hover:scale-105 focus-visible:ring-2", customSelected && "ring-ring ring-2"),
|
|
181
|
+
style: customColor ? { backgroundColor: customColor } : { backgroundImage: customGradient },
|
|
182
|
+
type: "button"
|
|
183
|
+
}),
|
|
184
|
+
children: customSelected ? /* @__PURE__ */ jsx(CheckIcon, { className: "bg-background/88 text-foreground pointer-events-none size-5 rounded-full p-0.5 shadow-sm" }) : null
|
|
185
|
+
}), /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
|
|
186
|
+
align: "end",
|
|
187
|
+
className: OVERLAY_LAYER_CLASS_NAMES.popup,
|
|
188
|
+
side: "bottom",
|
|
189
|
+
sideOffset: 4,
|
|
190
|
+
children: /* @__PURE__ */ jsx(Popover.Popup, {
|
|
191
|
+
className: "bg-popover text-popover-foreground flex w-56 flex-col gap-2 rounded-lg border p-2 shadow-lg/5",
|
|
192
|
+
"data-slot": "color-picker-custom-popup",
|
|
193
|
+
children: /* @__PURE__ */ jsx(CustomColorControls, {
|
|
194
|
+
handleInputChange,
|
|
195
|
+
handlePickerChange,
|
|
196
|
+
inputHex,
|
|
197
|
+
pickerHex
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
}) })] });
|
|
201
|
+
};
|
|
202
|
+
const ColorPickerContent = ({ value, onSelect, onClear, presets, columns, defaultExpanded, moreLabel, presentation = "popover" }) => {
|
|
131
203
|
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
132
204
|
const [pickerHex, setPickerHex] = useState(() => (looksLikeHex(value ?? "") ? value : "000000") ?? "000000");
|
|
133
205
|
const [inputHex, setInputHex] = useState("");
|
|
206
|
+
const customSelected = !presets.some((preset) => preset.value === value) && looksLikeHex(value ?? "");
|
|
134
207
|
/** Called when the visual picker (SB square / hue strip) emits a color. */
|
|
135
208
|
const handlePickerChange = (hex) => {
|
|
136
209
|
const normalized = normalizeHex(hex);
|
|
@@ -147,6 +220,27 @@ const ColorPickerContent = ({ value, onSelect, onClear, presets, columns, defaul
|
|
|
147
220
|
onSelect?.(cleaned);
|
|
148
221
|
}
|
|
149
222
|
};
|
|
223
|
+
if (presentation === "inline") return /* @__PURE__ */ jsxs("div", {
|
|
224
|
+
className: "flex items-center gap-1",
|
|
225
|
+
"data-slot": "color-picker",
|
|
226
|
+
children: [presets.map((preset) => /* @__PURE__ */ jsx(ColorSwatch, {
|
|
227
|
+
cssColor: swatchColor(preset),
|
|
228
|
+
isLight: looksLikeHex(preset.value) && isLightHex(preset.value),
|
|
229
|
+
label: preset.label,
|
|
230
|
+
onClick: () => onSelect?.(preset.value),
|
|
231
|
+
presentation: "inline",
|
|
232
|
+
selected: value === preset.value
|
|
233
|
+
}, preset.value)), /* @__PURE__ */ jsx(InlineCustomColor, {
|
|
234
|
+
customSelected,
|
|
235
|
+
handleInputChange,
|
|
236
|
+
handlePickerChange,
|
|
237
|
+
inputHex,
|
|
238
|
+
label: moreLabel,
|
|
239
|
+
pickerHex,
|
|
240
|
+
presets,
|
|
241
|
+
value
|
|
242
|
+
})]
|
|
243
|
+
});
|
|
150
244
|
return /* @__PURE__ */ jsxs("div", {
|
|
151
245
|
className: "flex flex-col gap-1.5",
|
|
152
246
|
"data-slot": "color-picker",
|
|
@@ -172,6 +266,7 @@ const ColorPickerContent = ({ value, onSelect, onClear, presets, columns, defaul
|
|
|
172
266
|
isLight: looksLikeHex(preset.value) && isLightHex(preset.value),
|
|
173
267
|
label: preset.label,
|
|
174
268
|
onClick: () => onSelect?.(preset.value),
|
|
269
|
+
presentation: "popover",
|
|
175
270
|
selected: value === preset.value
|
|
176
271
|
}, preset.value))
|
|
177
272
|
}),
|
|
@@ -180,43 +275,14 @@ const ColorPickerContent = ({ value, onSelect, onClear, presets, columns, defaul
|
|
|
180
275
|
onClick: () => setExpanded(true),
|
|
181
276
|
type: "button",
|
|
182
277
|
children: [moreLabel, /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3" })]
|
|
183
|
-
}) : /* @__PURE__ */
|
|
278
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
184
279
|
className: "border-border flex flex-col gap-2 border-t pt-2",
|
|
185
|
-
children:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
className: "ring-border/30 !h-[140px] !w-full overflow-hidden rounded-lg ring-1",
|
|
192
|
-
color: pickerHex,
|
|
193
|
-
onChange: (hex) => handlePickerChange(hex.replace("#", ""))
|
|
194
|
-
})
|
|
195
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
196
|
-
className: "flex items-center gap-1.5",
|
|
197
|
-
children: [
|
|
198
|
-
/* @__PURE__ */ jsx("span", {
|
|
199
|
-
className: "text-muted-foreground text-[11px]",
|
|
200
|
-
children: "#"
|
|
201
|
-
}),
|
|
202
|
-
/* @__PURE__ */ jsx("input", {
|
|
203
|
-
"aria-label": "Custom hex color",
|
|
204
|
-
className: "border-input bg-background text-foreground h-6 flex-1 rounded border px-1.5 font-mono text-[11px] outline-none",
|
|
205
|
-
dir: "ltr",
|
|
206
|
-
maxLength: 6,
|
|
207
|
-
onChange: (e) => handleInputChange(e.target.value),
|
|
208
|
-
onKeyDown: (e) => e.stopPropagation(),
|
|
209
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
210
|
-
onPointerDown: (e) => e.stopPropagation(),
|
|
211
|
-
placeholder: "FF0000",
|
|
212
|
-
value: inputHex
|
|
213
|
-
}),
|
|
214
|
-
isValidHex(inputHex) && /* @__PURE__ */ jsx("span", {
|
|
215
|
-
className: "border-border size-6 shrink-0 rounded border",
|
|
216
|
-
style: { backgroundColor: `#${inputHex}` }
|
|
217
|
-
})
|
|
218
|
-
]
|
|
219
|
-
})]
|
|
280
|
+
children: /* @__PURE__ */ jsx(CustomColorControls, {
|
|
281
|
+
handleInputChange,
|
|
282
|
+
handlePickerChange,
|
|
283
|
+
inputHex,
|
|
284
|
+
pickerHex
|
|
285
|
+
})
|
|
220
286
|
})
|
|
221
287
|
]
|
|
222
288
|
});
|
|
@@ -228,7 +294,7 @@ const ColorPicker = ({ value, onSelect, onClear, presets = DEFAULT_PRESETS, colu
|
|
|
228
294
|
children
|
|
229
295
|
}), /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
|
|
230
296
|
align,
|
|
231
|
-
className:
|
|
297
|
+
className: OVERLAY_LAYER_CLASS_NAMES.popup,
|
|
232
298
|
side,
|
|
233
299
|
sideOffset: 4,
|
|
234
300
|
children: /* @__PURE__ */ jsx(Popover.Popup, {
|
|
@@ -240,6 +306,7 @@ const ColorPicker = ({ value, onSelect, onClear, presets = DEFAULT_PRESETS, colu
|
|
|
240
306
|
moreLabel,
|
|
241
307
|
onClear,
|
|
242
308
|
onSelect,
|
|
309
|
+
presentation: "popover",
|
|
243
310
|
presets,
|
|
244
311
|
value
|
|
245
312
|
})
|
|
@@ -5,7 +5,7 @@ import { VariantProps } from "class-variance-authority";
|
|
|
5
5
|
//#region src/components/input-group.d.ts
|
|
6
6
|
declare const InputGroup: ({ className, ...props }: React$1.ComponentProps<"div">) => React$1.JSX.Element;
|
|
7
7
|
declare const inputGroupAddonVariants: (props?: ({
|
|
8
|
-
align?: "inline-end" | "inline-start" | "block-
|
|
8
|
+
align?: "inline-end" | "inline-start" | "block-start" | "block-end" | null | undefined;
|
|
9
9
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
10
10
|
declare const InputGroupAddon: ({ className, align, ...props }: React$1.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) => React$1.JSX.Element;
|
|
11
11
|
declare const InputGroupText: ({ className, ...props }: React$1.ComponentProps<"span">) => React$1.JSX.Element;
|
|
@@ -30,7 +30,7 @@ declare function useSidebar(): SidebarContextProps;
|
|
|
30
30
|
* left for the content column. Mobile reports 0: there the sidebar is an
|
|
31
31
|
* overlay sheet and occupies no layout width.
|
|
32
32
|
*/
|
|
33
|
-
declare function useSidebarInlineSize(): 0 |
|
|
33
|
+
declare function useSidebarInlineSize(): 0 | 48 | 256;
|
|
34
34
|
declare const SidebarProvider: ({ defaultOpen, forceCollapsed, open: openProp, onOpenChange: setOpenProp, className, style, children, ...props }: React.ComponentProps<"div"> & {
|
|
35
35
|
defaultOpen?: boolean;
|
|
36
36
|
forceCollapsed?: boolean;
|
|
@@ -83,7 +83,7 @@ declare const SidebarMenu: ({ className, ...props }: React.ComponentProps<"ul">)
|
|
|
83
83
|
declare const SidebarMenuItem: ({ className, ...props }: React.ComponentProps<"li">) => import("react").JSX.Element;
|
|
84
84
|
declare const sidebarMenuButtonVariants: (props?: ({
|
|
85
85
|
variant?: "default" | "outline" | null | undefined;
|
|
86
|
-
size?: "default" | "
|
|
86
|
+
size?: "default" | "sm" | "lg" | "rail" | null | undefined;
|
|
87
87
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
88
88
|
declare const SidebarMenuButton: ({ asChild, isActive, variant, size, tooltip, className, ...props }: React.ComponentProps<"button"> & {
|
|
89
89
|
asChild?: boolean;
|
package/dist/inspector/tabs.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { Tabs } from "@base-ui/react/tabs";
|
|
|
8
8
|
*/
|
|
9
9
|
declare const InspectorTabs: ({ className, ...props }: Omit<Tabs.Root.Props, "orientation">) => React$1.JSX.Element;
|
|
10
10
|
declare const INSPECTOR_RAIL_MEDIA_QUERY: "(min-width: 48rem)";
|
|
11
|
-
declare const resolveInspectorTabOrientation: (isRailLayout: boolean) => "
|
|
11
|
+
declare const resolveInspectorTabOrientation: (isRailLayout: boolean) => "horizontal" | "vertical";
|
|
12
12
|
declare const InspectorTabList: ({ className, ...props }: Tabs.List.Props) => React$1.JSX.Element;
|
|
13
13
|
declare const InspectorTab: ({ className, ...props }: Tabs.Tab.Props) => React$1.JSX.Element;
|
|
14
14
|
declare const InspectorTabPanel: ({ className, ...props }: Tabs.Panel.Props) => React$1.JSX.Element;
|
|
@@ -5,6 +5,6 @@ declare const CONTROL_SIZE: Readonly<{
|
|
|
5
5
|
readonly lg: "lg";
|
|
6
6
|
}>;
|
|
7
7
|
type ControlSize = (typeof CONTROL_SIZE)[keyof typeof CONTROL_SIZE];
|
|
8
|
-
declare const CONTROL_SIZES: readonly ("default" | "
|
|
8
|
+
declare const CONTROL_SIZES: readonly ("default" | "sm" | "lg")[];
|
|
9
9
|
//#endregion
|
|
10
10
|
export { CONTROL_SIZE, CONTROL_SIZES, type ControlSize };
|
package/package.json
CHANGED