@keboola/design 9.0.0 → 10.1.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/AGENTS.md +117 -40
- package/COMPONENT-API.md +31 -9
- package/README.md +3 -3
- package/dist/MermaidDiagram-EOKJHQQV.js +10 -0
- package/dist/MermaidDiagram-EOKJHQQV.js.map +1 -0
- package/dist/charts.d.ts +31 -2
- package/dist/charts.js +6 -9
- package/dist/charts.js.map +1 -1
- package/dist/chunk-63NSN2VL.js +274 -0
- package/dist/chunk-63NSN2VL.js.map +1 -0
- package/dist/{rjsf.cjs → chunk-6FPEI4EM.js} +1560 -5712
- package/dist/chunk-6FPEI4EM.js.map +1 -0
- package/dist/chunk-7PUUHEJQ.js +1313 -0
- package/dist/chunk-7PUUHEJQ.js.map +1 -0
- package/dist/chunk-BOHNXTMM.js +606 -0
- package/dist/chunk-BOHNXTMM.js.map +1 -0
- package/dist/{testing.cjs → chunk-C3L3TBBT.js} +33 -164
- package/dist/chunk-C3L3TBBT.js.map +1 -0
- package/dist/chunk-CTCFYWJC.js +407 -0
- package/dist/chunk-CTCFYWJC.js.map +1 -0
- package/dist/chunk-ESBL3IPF.js +23 -0
- package/dist/chunk-ESBL3IPF.js.map +1 -0
- package/dist/chunk-IJTHFNNJ.js +261 -0
- package/dist/chunk-IJTHFNNJ.js.map +1 -0
- package/dist/chunk-JP7PNHLH.js +40 -0
- package/dist/chunk-JP7PNHLH.js.map +1 -0
- package/dist/chunk-KPNAW5MU.js +229 -0
- package/dist/chunk-KPNAW5MU.js.map +1 -0
- package/dist/chunk-L37JJ6MR.js +152 -0
- package/dist/chunk-L37JJ6MR.js.map +1 -0
- package/dist/chunk-Q7NWXLCT.js +90 -0
- package/dist/chunk-Q7NWXLCT.js.map +1 -0
- package/dist/chunk-SYIEF644.js +1016 -0
- package/dist/chunk-SYIEF644.js.map +1 -0
- package/dist/chunk-VMFSRV5H.js +16 -0
- package/dist/chunk-VMFSRV5H.js.map +1 -0
- package/dist/chunk-VPPM7UUQ.js +47 -0
- package/dist/chunk-VPPM7UUQ.js.map +1 -0
- package/dist/chunk-XV3UUOYF.js +845 -0
- package/dist/chunk-XV3UUOYF.js.map +1 -0
- package/dist/editors.d.ts +53 -5
- package/dist/editors.js +85 -2097
- package/dist/editors.js.map +1 -1
- package/dist/icons.d.ts +29 -8
- package/dist/icons.js +2 -361
- package/dist/icons.js.map +1 -1
- package/dist/index.d.ts +735 -426
- package/dist/index.js +5029 -13796
- package/dist/index.js.map +1 -1
- package/dist/markdown-editor.js +41 -3426
- package/dist/markdown-editor.js.map +1 -1
- package/dist/mermaid.js +8 -1129
- package/dist/mermaid.js.map +1 -1
- package/dist/rjsf.js +97 -9240
- package/dist/rjsf.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/testing.js +5 -357
- package/dist/testing.js.map +1 -1
- package/package.json +29 -74
- package/src/styles.css +60 -3
- package/src/theme.css +1 -0
- package/dist/charts.cjs +0 -268
- package/dist/charts.cjs.map +0 -1
- package/dist/charts.d.cts +0 -181
- package/dist/constants-D3gaMY-W.d.cts +0 -39
- package/dist/editors.cjs +0 -2456
- package/dist/editors.cjs.map +0 -1
- package/dist/editors.d.cts +0 -141
- package/dist/icons.cjs +0 -23888
- package/dist/icons.cjs.map +0 -1
- package/dist/icons.d.cts +0 -20
- package/dist/index.cjs +0 -24817
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -10413
- package/dist/markdown-editor.cjs +0 -4636
- package/dist/markdown-editor.cjs.map +0 -1
- package/dist/markdown-editor.d.cts +0 -75
- package/dist/mermaid.cjs +0 -1138
- package/dist/mermaid.cjs.map +0 -1
- package/dist/mermaid.d.cts +0 -15
- package/dist/rjsf.cjs.map +0 -1
- package/dist/rjsf.d.cts +0 -55
- package/dist/testing.cjs.map +0 -1
- package/dist/testing.d.cts +0 -25
|
@@ -0,0 +1,1016 @@
|
|
|
1
|
+
import { HelpBlock } from './chunk-ESBL3IPF.js';
|
|
2
|
+
import { Button } from './chunk-CTCFYWJC.js';
|
|
3
|
+
import { X, Pipette } from './chunk-BOHNXTMM.js';
|
|
4
|
+
import { useArgoDesign } from './chunk-63NSN2VL.js';
|
|
5
|
+
import { cn } from './chunk-JP7PNHLH.js';
|
|
6
|
+
import * as ScrollAreaPrimitive2 from '@radix-ui/react-scroll-area';
|
|
7
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
|
+
import * as RLabel from '@radix-ui/react-label';
|
|
9
|
+
import { cva } from 'class-variance-authority';
|
|
10
|
+
import TextareaAutosize from 'react-textarea-autosize';
|
|
11
|
+
import { createContext, useState, useRef, useCallback, useMemo, use } from 'react';
|
|
12
|
+
|
|
13
|
+
// src/utils/mergeRefs.ts
|
|
14
|
+
function setRef(ref, value) {
|
|
15
|
+
if (typeof ref === "function") {
|
|
16
|
+
ref(value);
|
|
17
|
+
} else if (ref != null) {
|
|
18
|
+
ref.current = value;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
var mergeRefs = (...refs) => {
|
|
22
|
+
return (node) => refs.forEach((ref) => setRef(ref, node));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// src/utils/createChangeInputEvent.ts
|
|
26
|
+
var createChangeInputEvent = (input) => {
|
|
27
|
+
const changeEvent = {
|
|
28
|
+
target: input,
|
|
29
|
+
currentTarget: input,
|
|
30
|
+
type: "change",
|
|
31
|
+
nativeEvent: new Event("change", { bubbles: true }),
|
|
32
|
+
bubbles: true,
|
|
33
|
+
cancelable: false,
|
|
34
|
+
defaultPrevented: false,
|
|
35
|
+
eventPhase: 2,
|
|
36
|
+
// AT_TARGET
|
|
37
|
+
isTrusted: false,
|
|
38
|
+
// Synthetic events are not trusted
|
|
39
|
+
preventDefault: () => {
|
|
40
|
+
},
|
|
41
|
+
// Provide dummy functions if not needed
|
|
42
|
+
isDefaultPrevented: () => false,
|
|
43
|
+
stopPropagation: () => {
|
|
44
|
+
},
|
|
45
|
+
isPropagationStopped: () => false,
|
|
46
|
+
persist: () => {
|
|
47
|
+
},
|
|
48
|
+
timeStamp: Date.now()
|
|
49
|
+
};
|
|
50
|
+
Object.defineProperty(changeEvent, "target", {
|
|
51
|
+
value: input,
|
|
52
|
+
writable: false
|
|
53
|
+
});
|
|
54
|
+
return changeEvent;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// src/utils/createPrefixedString.ts
|
|
58
|
+
var createPrefixedString = (prefix) => (literals) => literals.reduce((acc, literal) => acc + literal, `${prefix}-`);
|
|
59
|
+
var ScrollBar = ({ className, orientation = "vertical", ...props }) => /* @__PURE__ */ jsx(
|
|
60
|
+
ScrollAreaPrimitive2.ScrollAreaScrollbar,
|
|
61
|
+
{
|
|
62
|
+
orientation,
|
|
63
|
+
className: cn(
|
|
64
|
+
"tw:flex tw:touch-none tw:select-none tw:transition-color",
|
|
65
|
+
{
|
|
66
|
+
"tw:h-full tw:w-2.5 tw:p-px": orientation === "vertical",
|
|
67
|
+
"tw:h-2.5 tw:flex-col tw:p-px": orientation === "horizontal"
|
|
68
|
+
},
|
|
69
|
+
className
|
|
70
|
+
),
|
|
71
|
+
...props,
|
|
72
|
+
children: /* @__PURE__ */ jsx(
|
|
73
|
+
ScrollAreaPrimitive2.ScrollAreaThumb,
|
|
74
|
+
{
|
|
75
|
+
className: cn(
|
|
76
|
+
"tw:relative",
|
|
77
|
+
"tw:flex-1",
|
|
78
|
+
"tw:rounded-full",
|
|
79
|
+
"tw:bg-border",
|
|
80
|
+
"tw:hover:bg-muted-foreground"
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
var ScrollArea = ({
|
|
87
|
+
ref,
|
|
88
|
+
className,
|
|
89
|
+
children,
|
|
90
|
+
viewPortClassName,
|
|
91
|
+
orientation,
|
|
92
|
+
scrollBarClassName,
|
|
93
|
+
...props
|
|
94
|
+
}) => /* @__PURE__ */ jsxs(
|
|
95
|
+
ScrollAreaPrimitive2.Root,
|
|
96
|
+
{
|
|
97
|
+
"data-slot": "scroll-area",
|
|
98
|
+
className: cn(
|
|
99
|
+
"tw:peer/scroll-area tw:relative tw:overflow-hidden tw:focus-visible:outline-hidden",
|
|
100
|
+
className
|
|
101
|
+
),
|
|
102
|
+
...props,
|
|
103
|
+
children: [
|
|
104
|
+
/* @__PURE__ */ jsx(
|
|
105
|
+
ScrollAreaPrimitive2.Viewport,
|
|
106
|
+
{
|
|
107
|
+
ref,
|
|
108
|
+
className: cn(
|
|
109
|
+
"tw:h-full tw:w-full tw:rounded-[inherit] tw:focus-visible:outline-hidden",
|
|
110
|
+
viewPortClassName
|
|
111
|
+
),
|
|
112
|
+
children
|
|
113
|
+
}
|
|
114
|
+
),
|
|
115
|
+
orientation ? /* @__PURE__ */ jsx(ScrollBar, { className: scrollBarClassName, orientation }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
116
|
+
/* @__PURE__ */ jsx(ScrollBar, { className: scrollBarClassName, orientation: "vertical" }),
|
|
117
|
+
/* @__PURE__ */ jsx(ScrollBar, { className: scrollBarClassName, orientation: "horizontal" })
|
|
118
|
+
] }),
|
|
119
|
+
/* @__PURE__ */ jsx(ScrollAreaPrimitive2.Corner, {})
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
var Optional = ({ className, ...props }) => /* @__PURE__ */ jsx("span", { ...props, "aria-hidden": true, className: cn("tw:ml-0.5", "tw:text-muted-foreground", className), children: "(optional)" });
|
|
124
|
+
var Required = ({ className, ...props }) => /* @__PURE__ */ jsx("span", { ...props, "aria-hidden": true, className: cn("tw:ml-0.5", "tw:text-primary", className), children: "*" });
|
|
125
|
+
var Label = ({ className, children, id, htmlFor, ...rest }) => /* @__PURE__ */ jsx(
|
|
126
|
+
RLabel.Root,
|
|
127
|
+
{
|
|
128
|
+
...rest,
|
|
129
|
+
id: id?.toString(),
|
|
130
|
+
htmlFor: htmlFor?.toString(),
|
|
131
|
+
className: cn(
|
|
132
|
+
"tw:m-0 tw:text-foreground tw:font-normal tw:peer-disabled:opacity-50",
|
|
133
|
+
className
|
|
134
|
+
),
|
|
135
|
+
children
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
Label.Optional = Optional;
|
|
139
|
+
Label.Required = Required;
|
|
140
|
+
var addonVariants = cva(
|
|
141
|
+
[
|
|
142
|
+
"tw:flex",
|
|
143
|
+
"tw:items-center",
|
|
144
|
+
"tw:gap-1",
|
|
145
|
+
// Default size for nested Lucide icons in prefix/suffix slots; callers can override on the icon.
|
|
146
|
+
"tw:[&_svg.lucide:not([class*='tw:size-'])]:size-4",
|
|
147
|
+
"tw:[&_svg]:shrink-0"
|
|
148
|
+
],
|
|
149
|
+
{
|
|
150
|
+
defaultVariants: {
|
|
151
|
+
align: "inline-start"
|
|
152
|
+
},
|
|
153
|
+
variants: {
|
|
154
|
+
align: {
|
|
155
|
+
"inline-start": ["tw:order-first", "tw:[&:not(:empty)]:pl-4"],
|
|
156
|
+
"inline-end": ["tw:order-last", "tw:[&:not(:empty)]:pr-4"],
|
|
157
|
+
"block-start": [
|
|
158
|
+
"tw:order-first",
|
|
159
|
+
// `tw:w-full` needs to be empty-conditional too — when the addon
|
|
160
|
+
// has no content the root stays in flex-row, and a 100%-wide
|
|
161
|
+
// empty addon would claim half of the input row beside the input.
|
|
162
|
+
"tw:[&:not(:empty)]:w-full",
|
|
163
|
+
"tw:[&:not(:empty)]:px-4",
|
|
164
|
+
"tw:[&:not(:empty)]:py-1.5"
|
|
165
|
+
],
|
|
166
|
+
"block-end": [
|
|
167
|
+
"tw:order-last",
|
|
168
|
+
"tw:[&:not(:empty)]:w-full",
|
|
169
|
+
"tw:[&:not(:empty)]:px-4",
|
|
170
|
+
"tw:[&:not(:empty)]:py-1.5"
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
var InputGroupAddon = ({
|
|
177
|
+
children,
|
|
178
|
+
align = "inline-start",
|
|
179
|
+
className,
|
|
180
|
+
...props
|
|
181
|
+
}) => /* @__PURE__ */ jsx("div", { ...props, "data-align": align, className: cn(addonVariants({ align, className })), children });
|
|
182
|
+
var InputGroupButton = ({ ref, className, tabIndex = -1, ...props }) => /* @__PURE__ */ jsx(
|
|
183
|
+
Button,
|
|
184
|
+
{
|
|
185
|
+
...props,
|
|
186
|
+
tabIndex,
|
|
187
|
+
ref,
|
|
188
|
+
variant: "invisible",
|
|
189
|
+
size: "icon-sm",
|
|
190
|
+
className: cn("tw:size-5", "tw:[&_svg]:text-muted-foreground", className)
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
var InputGroupInput = ({ ref, className, ...inputProps }) => /* @__PURE__ */ jsx(
|
|
194
|
+
"input",
|
|
195
|
+
{
|
|
196
|
+
...inputProps,
|
|
197
|
+
ref,
|
|
198
|
+
className: cn(
|
|
199
|
+
"tw:w-full",
|
|
200
|
+
"tw:bg-transparent",
|
|
201
|
+
"tw:outline-hidden",
|
|
202
|
+
// font
|
|
203
|
+
"tw:font-sans",
|
|
204
|
+
"tw:text-sm",
|
|
205
|
+
// placeholder
|
|
206
|
+
"tw:placeholder:text-neutral-400",
|
|
207
|
+
"tw:placeholder:font-normal",
|
|
208
|
+
// disabled
|
|
209
|
+
"tw:disabled:cursor-not-allowed",
|
|
210
|
+
className
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
var InputGroupText = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
215
|
+
"span",
|
|
216
|
+
{
|
|
217
|
+
className: cn(
|
|
218
|
+
"tw:flex",
|
|
219
|
+
"tw:items-center",
|
|
220
|
+
"tw:gap-2",
|
|
221
|
+
"tw:text-sm",
|
|
222
|
+
"tw:text-muted-foreground",
|
|
223
|
+
"tw:[&_svg]:pointer-events-none",
|
|
224
|
+
'tw:[&_svg:not([class*="tw:size-"])]:size-4',
|
|
225
|
+
className
|
|
226
|
+
),
|
|
227
|
+
...props
|
|
228
|
+
}
|
|
229
|
+
);
|
|
230
|
+
var InputGroupTextArea = ({
|
|
231
|
+
ref,
|
|
232
|
+
className,
|
|
233
|
+
onChange,
|
|
234
|
+
onValueChange,
|
|
235
|
+
value,
|
|
236
|
+
defaultValue,
|
|
237
|
+
onBlur,
|
|
238
|
+
onValueBlur,
|
|
239
|
+
disableResize = false,
|
|
240
|
+
minRows = 1,
|
|
241
|
+
maxRows = 4,
|
|
242
|
+
...props
|
|
243
|
+
}) => {
|
|
244
|
+
const handleChange = (event) => {
|
|
245
|
+
onValueChange?.(event.target.value);
|
|
246
|
+
onChange?.(event);
|
|
247
|
+
};
|
|
248
|
+
const handleBlur = (event) => {
|
|
249
|
+
onValueBlur?.(event.target.value);
|
|
250
|
+
onBlur?.(event);
|
|
251
|
+
};
|
|
252
|
+
return /* @__PURE__ */ jsx(
|
|
253
|
+
TextareaAutosize,
|
|
254
|
+
{
|
|
255
|
+
...props,
|
|
256
|
+
ref,
|
|
257
|
+
value: value ?? void 0,
|
|
258
|
+
defaultValue: defaultValue ?? void 0,
|
|
259
|
+
onChange: handleChange,
|
|
260
|
+
onBlur: handleBlur,
|
|
261
|
+
minRows,
|
|
262
|
+
maxRows: maxRows === "unlimited" ? void 0 : maxRows,
|
|
263
|
+
className: cn(
|
|
264
|
+
"tw:w-full",
|
|
265
|
+
"tw:bg-transparent",
|
|
266
|
+
"tw:outline-hidden",
|
|
267
|
+
"tw:px-4",
|
|
268
|
+
// font
|
|
269
|
+
"tw:font-sans",
|
|
270
|
+
"tw:text-sm",
|
|
271
|
+
// placeholder
|
|
272
|
+
"tw:placeholder:text-neutral-400",
|
|
273
|
+
"tw:placeholder:font-normal",
|
|
274
|
+
// disabled
|
|
275
|
+
"tw:disabled:cursor-not-allowed",
|
|
276
|
+
{
|
|
277
|
+
"tw:resize-none": disableResize
|
|
278
|
+
},
|
|
279
|
+
className
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
);
|
|
283
|
+
};
|
|
284
|
+
var inputGroupVariants = cva(
|
|
285
|
+
[
|
|
286
|
+
"tailwindcss-preflight",
|
|
287
|
+
"tw:group",
|
|
288
|
+
"tw:overflow-hidden",
|
|
289
|
+
"tw:box-border",
|
|
290
|
+
// positioning
|
|
291
|
+
"tw:flex",
|
|
292
|
+
"tw:items-center",
|
|
293
|
+
// base — legacy (non-argo) chrome uses a fixed radius; argo overrides it with
|
|
294
|
+
// the brand radius token in the `argo` variant below.
|
|
295
|
+
"tw:rounded",
|
|
296
|
+
"tw:border",
|
|
297
|
+
"tw:border-solid",
|
|
298
|
+
// `border-input` rather than the fixed `neutral-200` — same light-scheme
|
|
299
|
+
// grey, but it follows the dark scheme too. The base text stays pinned:
|
|
300
|
+
// `secondary` and the readonly state below both fill with a fixed light
|
|
301
|
+
// grey, so a scheme-following text colour would go light-on-light there.
|
|
302
|
+
// `primary` opts into the token itself (and re-pins its readonly fill).
|
|
303
|
+
"tw:border-input",
|
|
304
|
+
"tw:text-neutral-800",
|
|
305
|
+
"tw:transition",
|
|
306
|
+
// focus
|
|
307
|
+
"tw:has-[:is(input,textarea):focus]:ring-4",
|
|
308
|
+
// readonly
|
|
309
|
+
"tw:has-[:is(input,textarea)[readonly]]:bg-neutral-150",
|
|
310
|
+
"tw:has-[:is(input,textarea)[readonly]]:focus-within:ring-0",
|
|
311
|
+
"tw:has-[:is(input,textarea)[readonly]]:border-neutral-150",
|
|
312
|
+
// disabled cursor (opacity owned by variant)
|
|
313
|
+
"tw:has-[:is(input,textarea):disabled]:cursor-not-allowed",
|
|
314
|
+
// textarea: top-align addons, allow vertical expansion, own its y-padding
|
|
315
|
+
"tw:has-[textarea]:items-start",
|
|
316
|
+
"tw:has-[[data-align=block-start]:not(:empty)]:flex-wrap",
|
|
317
|
+
"tw:has-[[data-align=block-end]:not(:empty)]:flex-wrap",
|
|
318
|
+
"tw:[&>input]:has-[[data-align=block-start]:not(:empty)]:w-auto",
|
|
319
|
+
"tw:[&>input]:has-[[data-align=block-start]:not(:empty)]:flex-1",
|
|
320
|
+
"tw:[&>input]:has-[[data-align=block-end]:not(:empty)]:w-auto",
|
|
321
|
+
"tw:[&>input]:has-[[data-align=block-end]:not(:empty)]:flex-1",
|
|
322
|
+
"tw:[&>input]:px-4",
|
|
323
|
+
"tw:[&>input]:has-[[data-align=inline-start]:not(:empty)]:pl-2",
|
|
324
|
+
"tw:[&>input]:has-[[data-align=inline-end]:not(:empty)]:pr-2"
|
|
325
|
+
],
|
|
326
|
+
{
|
|
327
|
+
defaultVariants: {
|
|
328
|
+
variant: "primary",
|
|
329
|
+
state: "default",
|
|
330
|
+
sizing: "medium",
|
|
331
|
+
focusVariant: "default"
|
|
332
|
+
},
|
|
333
|
+
compoundVariants: [
|
|
334
|
+
{
|
|
335
|
+
variant: "secondary",
|
|
336
|
+
state: "error",
|
|
337
|
+
className: ["tw:bg-error-100"]
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
variant: "secondary",
|
|
341
|
+
state: "warning",
|
|
342
|
+
className: ["tw:bg-warning-100"]
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
variant: "primary",
|
|
346
|
+
state: "default",
|
|
347
|
+
focusVariant: "off",
|
|
348
|
+
className: ["tw:has-[:is(input,textarea):focus]:border-neutral-200"]
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
variant: "secondary",
|
|
352
|
+
state: "default",
|
|
353
|
+
focusVariant: "off",
|
|
354
|
+
className: ["tw:has-[:is(input,textarea):focus]:border-neutral-100"]
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
variant: ["primary", "secondary"],
|
|
358
|
+
state: "error",
|
|
359
|
+
focusVariant: "on",
|
|
360
|
+
className: ["tw:!border-error-500", "tw:!ring-error-200"]
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
variant: ["primary", "secondary"],
|
|
364
|
+
state: "warning",
|
|
365
|
+
focusVariant: "on",
|
|
366
|
+
className: ["tw:!border-warning-500", "tw:!ring-warning-200"]
|
|
367
|
+
},
|
|
368
|
+
// --- argo ---
|
|
369
|
+
{
|
|
370
|
+
variant: "argo",
|
|
371
|
+
state: "default",
|
|
372
|
+
className: [
|
|
373
|
+
"tw:has-[:is(input,textarea):focus]:border-primary",
|
|
374
|
+
"tw:has-[:is(input,textarea):focus]:ring-ring/50"
|
|
375
|
+
]
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
variant: "argo",
|
|
379
|
+
state: "error",
|
|
380
|
+
className: [
|
|
381
|
+
"tw:border-destructive",
|
|
382
|
+
"tw:has-[:is(input,textarea):focus]:border-destructive",
|
|
383
|
+
"tw:has-[:is(input,textarea):focus]:ring-destructive/20"
|
|
384
|
+
]
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
variant: "argo",
|
|
388
|
+
focusVariant: "on",
|
|
389
|
+
className: ["tw:!border-primary", "tw:!ring-ring/50"]
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
variant: "argo",
|
|
393
|
+
state: "error",
|
|
394
|
+
focusVariant: "on",
|
|
395
|
+
className: ["tw:!border-destructive", "tw:!ring-destructive/20"]
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
variant: "argo",
|
|
399
|
+
state: "default",
|
|
400
|
+
focusVariant: "off",
|
|
401
|
+
className: ["tw:has-[:is(input,textarea):focus]:border-input"]
|
|
402
|
+
}
|
|
403
|
+
],
|
|
404
|
+
variants: {
|
|
405
|
+
focusVariant: {
|
|
406
|
+
default: [],
|
|
407
|
+
on: ["tw:!border-ring", "tw:!ring-ring/30", "tw:!ring-4"],
|
|
408
|
+
off: ["tw:has-[:is(input,textarea):focus]:!ring-0"]
|
|
409
|
+
},
|
|
410
|
+
variant: {
|
|
411
|
+
primary: [
|
|
412
|
+
// The field-surface token — white in the light scheme, so this is a
|
|
413
|
+
// no-op there; the dark scheme gets a field fill, not a white slab.
|
|
414
|
+
"tw:bg-input-background",
|
|
415
|
+
"tw:text-foreground",
|
|
416
|
+
// The base readonly fill is a fixed light grey, which the scheme-following
|
|
417
|
+
// text above would sit on invisibly in dark. Re-pin to the same
|
|
418
|
+
// `muted`/`input` pair argo uses for exactly this reason.
|
|
419
|
+
"tw:has-[:is(input,textarea)[readonly]]:bg-muted",
|
|
420
|
+
"tw:has-[:is(input,textarea)[readonly]]:border-input",
|
|
421
|
+
"tw:has-[:is(input,textarea):disabled]:opacity-40",
|
|
422
|
+
// aria-invalid on the control surfaces the error chrome without a `state` prop — the
|
|
423
|
+
// accessible path (mirrors the `state="error"` legacy tokens). Higher specificity than
|
|
424
|
+
// the default focus selector, so it wins without `!important`.
|
|
425
|
+
"tw:has-[:is(input,textarea)[aria-invalid=true]]:border-error-500",
|
|
426
|
+
"tw:has-[:is(input,textarea)[aria-invalid=true]:focus]:border-error-500",
|
|
427
|
+
"tw:has-[:is(input,textarea)[aria-invalid=true]:focus]:ring-error-200"
|
|
428
|
+
],
|
|
429
|
+
secondary: [
|
|
430
|
+
"tw:bg-neutral-100",
|
|
431
|
+
"tw:border-neutral-100",
|
|
432
|
+
"tw:has-[:is(input,textarea):disabled]:opacity-40",
|
|
433
|
+
"tw:has-[:is(input,textarea)[aria-invalid=true]]:border-error-500",
|
|
434
|
+
"tw:has-[:is(input,textarea)[aria-invalid=true]:focus]:border-error-500",
|
|
435
|
+
"tw:has-[:is(input,textarea)[aria-invalid=true]:focus]:ring-error-200"
|
|
436
|
+
],
|
|
437
|
+
argo: [
|
|
438
|
+
// argo follows the brand radius token (overrides the static base)
|
|
439
|
+
"tw:rounded-[var(--radius-lg,0.25rem)]",
|
|
440
|
+
// muted filled input surface — gray, distinct from white containers; not the app-background token.
|
|
441
|
+
// Deliberately `muted`, not the `input-background` field token legacy uses: argo's field is a
|
|
442
|
+
// grey inset by design. Converging the two is a brand-value decision, not a component one.
|
|
443
|
+
"tw:bg-muted",
|
|
444
|
+
"tw:border-input",
|
|
445
|
+
"tw:text-foreground",
|
|
446
|
+
"tw:has-[:is(input,textarea):disabled]:opacity-50",
|
|
447
|
+
// readonly: keep the themed input surface/border. The base layer's fixed
|
|
448
|
+
// `neutral-150` (a light grey) is correct for the legacy light chrome but
|
|
449
|
+
// collides with argo's themed `foreground` text — light-on-light, invisible
|
|
450
|
+
// in dark mode. Re-pin to the same `muted`/`input` tokens the editable argo
|
|
451
|
+
// input uses (validated AA), so readonly stays legible in every scheme.
|
|
452
|
+
"tw:has-[:is(input,textarea)[readonly]]:bg-muted",
|
|
453
|
+
"tw:has-[:is(input,textarea)[readonly]]:border-input",
|
|
454
|
+
// higher specificity than has-[:is(input,textarea):focus] — prevents focus border on readonly
|
|
455
|
+
"tw:has-[:is(input,textarea)[readonly]:focus]:border-input",
|
|
456
|
+
// aria-invalid on the control surfaces the error chrome without a `state` prop — the
|
|
457
|
+
// accessible path (uses the themeable `destructive` status token).
|
|
458
|
+
"tw:has-[:is(input,textarea)[aria-invalid=true]]:border-destructive",
|
|
459
|
+
"tw:has-[:is(input,textarea)[aria-invalid=true]:focus]:border-destructive",
|
|
460
|
+
"tw:has-[:is(input,textarea)[aria-invalid=true]:focus]:ring-destructive/20"
|
|
461
|
+
]
|
|
462
|
+
},
|
|
463
|
+
sizing: {
|
|
464
|
+
default: [
|
|
465
|
+
"tw:[&>:is(input,textarea)]:py-2.5",
|
|
466
|
+
"tw:[&>:is(input,textarea)]:leading-[18px]",
|
|
467
|
+
"tw:[&>textarea]:!min-h-[calc(2.5rem-2px)]"
|
|
468
|
+
],
|
|
469
|
+
small: [
|
|
470
|
+
"tw:[&>:is(input,textarea)]:py-2",
|
|
471
|
+
"tw:[&>:is(input,textarea)]:leading-[16px]",
|
|
472
|
+
"tw:[&>textarea]:!min-h-[calc(2rem-2px)]"
|
|
473
|
+
],
|
|
474
|
+
medium: [
|
|
475
|
+
"tw:[&>:is(input,textarea)]:py-2",
|
|
476
|
+
"tw:[&>:is(input,textarea)]:leading-[18px]",
|
|
477
|
+
"tw:[&>textarea]:!min-h-[calc(2.25rem-2px)]"
|
|
478
|
+
]
|
|
479
|
+
},
|
|
480
|
+
state: {
|
|
481
|
+
default: [
|
|
482
|
+
"tw:has-[:is(input,textarea):focus]:border-ring",
|
|
483
|
+
"tw:has-[:is(input,textarea):focus]:ring-ring/30"
|
|
484
|
+
],
|
|
485
|
+
error: [
|
|
486
|
+
"tw:border-error-500",
|
|
487
|
+
"tw:has-[:is(input,textarea):focus]:border-error-500",
|
|
488
|
+
"tw:has-[:is(input,textarea):focus]:ring-error-200"
|
|
489
|
+
],
|
|
490
|
+
warning: [
|
|
491
|
+
"tw:border-warning-500",
|
|
492
|
+
"tw:has-[:is(input,textarea):focus]:border-warning-500",
|
|
493
|
+
"tw:has-[:is(input,textarea):focus]:ring-warning-200"
|
|
494
|
+
]
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
);
|
|
499
|
+
var InputGroupRoot = ({
|
|
500
|
+
ref,
|
|
501
|
+
children,
|
|
502
|
+
state,
|
|
503
|
+
variant,
|
|
504
|
+
sizing,
|
|
505
|
+
focusVariant,
|
|
506
|
+
className,
|
|
507
|
+
...props
|
|
508
|
+
}) => {
|
|
509
|
+
const isArgo = useArgoDesign();
|
|
510
|
+
const effectiveVariant = isArgo ? "argo" : variant;
|
|
511
|
+
const effectiveSizing = effectiveVariant === "argo" ? "medium" : sizing;
|
|
512
|
+
return /* @__PURE__ */ jsx(
|
|
513
|
+
"div",
|
|
514
|
+
{
|
|
515
|
+
...props,
|
|
516
|
+
ref,
|
|
517
|
+
className: cn(
|
|
518
|
+
inputGroupVariants({
|
|
519
|
+
state,
|
|
520
|
+
variant: effectiveVariant,
|
|
521
|
+
sizing: effectiveSizing,
|
|
522
|
+
focusVariant,
|
|
523
|
+
className
|
|
524
|
+
})
|
|
525
|
+
),
|
|
526
|
+
children
|
|
527
|
+
}
|
|
528
|
+
);
|
|
529
|
+
};
|
|
530
|
+
var InputGroup = InputGroupRoot;
|
|
531
|
+
InputGroup.Input = InputGroupInput;
|
|
532
|
+
InputGroup.Addon = InputGroupAddon;
|
|
533
|
+
InputGroup.Button = InputGroupButton;
|
|
534
|
+
InputGroup.TextArea = InputGroupTextArea;
|
|
535
|
+
InputGroup.Text = InputGroupText;
|
|
536
|
+
var useControllableState = ({
|
|
537
|
+
prop,
|
|
538
|
+
defaultProp,
|
|
539
|
+
onChange
|
|
540
|
+
}) => {
|
|
541
|
+
const [uncontrolled, setUncontrolled] = useState(defaultProp);
|
|
542
|
+
const isControlled = prop !== void 0;
|
|
543
|
+
const value = prop !== void 0 ? prop : uncontrolled;
|
|
544
|
+
const valueRef = useRef(value);
|
|
545
|
+
valueRef.current = value;
|
|
546
|
+
const onChangeRef = useRef(onChange);
|
|
547
|
+
onChangeRef.current = onChange;
|
|
548
|
+
const setValue = useCallback(
|
|
549
|
+
(next) => {
|
|
550
|
+
const nextValue = typeof next === "function" ? next(valueRef.current) : next;
|
|
551
|
+
valueRef.current = nextValue;
|
|
552
|
+
if (!isControlled) setUncontrolled(nextValue);
|
|
553
|
+
onChangeRef.current?.(nextValue);
|
|
554
|
+
},
|
|
555
|
+
[isControlled]
|
|
556
|
+
);
|
|
557
|
+
return [value, setValue];
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
// src/blocks/TextInput/utils.ts
|
|
561
|
+
var genInputTestId = (prefix = "") => {
|
|
562
|
+
const ps = createPrefixedString(prefix);
|
|
563
|
+
return {
|
|
564
|
+
toString: () => prefix,
|
|
565
|
+
inputWrapper: ps`input-wrapper`,
|
|
566
|
+
input: ps`input`,
|
|
567
|
+
clearButton: ps`clear-button`
|
|
568
|
+
};
|
|
569
|
+
};
|
|
570
|
+
var sanitizeTextInputValue = (value) => {
|
|
571
|
+
if (typeof value === "string" && value.trim() === "") return "";
|
|
572
|
+
return value;
|
|
573
|
+
};
|
|
574
|
+
var TextInput = ({
|
|
575
|
+
ref: forwardedRef,
|
|
576
|
+
state = "default",
|
|
577
|
+
sizing = "default",
|
|
578
|
+
className,
|
|
579
|
+
prefix = null,
|
|
580
|
+
rightSuffix = null,
|
|
581
|
+
rightSuffixVariant = "default",
|
|
582
|
+
leftSuffix = null,
|
|
583
|
+
allowClear = false,
|
|
584
|
+
onClear,
|
|
585
|
+
disabled = false,
|
|
586
|
+
testId: prefixTestId = "",
|
|
587
|
+
autoFocus = false,
|
|
588
|
+
id,
|
|
589
|
+
name,
|
|
590
|
+
variant,
|
|
591
|
+
readOnly,
|
|
592
|
+
type = "text",
|
|
593
|
+
focusVariant = "default",
|
|
594
|
+
onChange,
|
|
595
|
+
onBlur,
|
|
596
|
+
onValueChange,
|
|
597
|
+
onValueBlur,
|
|
598
|
+
value: valueProp,
|
|
599
|
+
defaultValue,
|
|
600
|
+
...inputProps
|
|
601
|
+
}) => {
|
|
602
|
+
const inputRef = useRef(null);
|
|
603
|
+
const [value, setValue] = useControllableState({
|
|
604
|
+
// `undefined` stays uncontrolled; any provided value (incl. `null`) is controlled and coerced
|
|
605
|
+
// to a string. Whitespace-only input collapses to '' via `sanitizeTextInputValue`.
|
|
606
|
+
prop: valueProp === void 0 ? void 0 : sanitizeTextInputValue(valueProp) ?? "",
|
|
607
|
+
defaultProp: sanitizeTextInputValue(defaultValue) ?? "",
|
|
608
|
+
onChange: onValueChange
|
|
609
|
+
});
|
|
610
|
+
const testId = genInputTestId(prefixTestId);
|
|
611
|
+
const isClearButtonVisible = !!value && !disabled && !readOnly || !!onClear;
|
|
612
|
+
const handleChange = (event) => {
|
|
613
|
+
setValue(event.target.value);
|
|
614
|
+
onChange?.(event);
|
|
615
|
+
};
|
|
616
|
+
const handleBlur = (event) => {
|
|
617
|
+
onValueBlur?.(event.target.value);
|
|
618
|
+
onBlur?.(event);
|
|
619
|
+
};
|
|
620
|
+
const handleClear = () => {
|
|
621
|
+
if (inputRef.current === null) return;
|
|
622
|
+
inputRef.current.value = "";
|
|
623
|
+
inputRef.current.focus();
|
|
624
|
+
onClear?.();
|
|
625
|
+
handleChange(createChangeInputEvent(inputRef.current));
|
|
626
|
+
};
|
|
627
|
+
return /* @__PURE__ */ jsxs(
|
|
628
|
+
InputGroup,
|
|
629
|
+
{
|
|
630
|
+
state,
|
|
631
|
+
variant,
|
|
632
|
+
sizing,
|
|
633
|
+
focusVariant,
|
|
634
|
+
className,
|
|
635
|
+
"data-testid": testId.inputWrapper,
|
|
636
|
+
children: [
|
|
637
|
+
prefix && /* @__PURE__ */ jsx(InputGroup.Addon, { align: "inline-start", children: prefix }),
|
|
638
|
+
/* @__PURE__ */ jsx(
|
|
639
|
+
InputGroup.Input,
|
|
640
|
+
{
|
|
641
|
+
...inputProps,
|
|
642
|
+
value,
|
|
643
|
+
autoFocus,
|
|
644
|
+
type,
|
|
645
|
+
onChange: handleChange,
|
|
646
|
+
onBlur: handleBlur,
|
|
647
|
+
ref: mergeRefs(forwardedRef ?? null, inputRef),
|
|
648
|
+
disabled,
|
|
649
|
+
id,
|
|
650
|
+
name,
|
|
651
|
+
readOnly,
|
|
652
|
+
"data-testid": testId.input
|
|
653
|
+
}
|
|
654
|
+
),
|
|
655
|
+
(leftSuffix || allowClear || rightSuffix) && /* @__PURE__ */ jsxs(InputGroup.Addon, { align: "inline-end", children: [
|
|
656
|
+
leftSuffix,
|
|
657
|
+
allowClear && isClearButtonVisible && /* @__PURE__ */ jsx(
|
|
658
|
+
InputGroup.Button,
|
|
659
|
+
{
|
|
660
|
+
"aria-label": "Clear",
|
|
661
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
662
|
+
onClick: handleClear,
|
|
663
|
+
"data-testid": testId.clearButton,
|
|
664
|
+
children: /* @__PURE__ */ jsx(X, { className: "tw:size-4" })
|
|
665
|
+
}
|
|
666
|
+
),
|
|
667
|
+
rightSuffix && /* @__PURE__ */ jsx(
|
|
668
|
+
"div",
|
|
669
|
+
{
|
|
670
|
+
className: cn({
|
|
671
|
+
"tw:whitespace-nowrap tw:bg-muted tw:px-4 tw:-mr-4 tw:py-2.5": rightSuffixVariant === "addon"
|
|
672
|
+
}),
|
|
673
|
+
children: rightSuffix
|
|
674
|
+
}
|
|
675
|
+
)
|
|
676
|
+
] })
|
|
677
|
+
]
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
};
|
|
681
|
+
var Textarea = ({
|
|
682
|
+
ref,
|
|
683
|
+
containerClassName,
|
|
684
|
+
// group props
|
|
685
|
+
state = "default",
|
|
686
|
+
variant,
|
|
687
|
+
sizing,
|
|
688
|
+
focusVariant,
|
|
689
|
+
// value handling
|
|
690
|
+
value: valueProp,
|
|
691
|
+
defaultValue,
|
|
692
|
+
onValueChange,
|
|
693
|
+
...rest
|
|
694
|
+
}) => {
|
|
695
|
+
const [value, setValue] = useControllableState({
|
|
696
|
+
// `undefined` stays uncontrolled; any provided value (incl. `null`) is controlled, coerced to ''.
|
|
697
|
+
prop: valueProp === void 0 ? void 0 : valueProp ?? "",
|
|
698
|
+
defaultProp: defaultValue ?? "",
|
|
699
|
+
onChange: onValueChange
|
|
700
|
+
});
|
|
701
|
+
return /* @__PURE__ */ jsx(
|
|
702
|
+
InputGroup,
|
|
703
|
+
{
|
|
704
|
+
state,
|
|
705
|
+
sizing,
|
|
706
|
+
focusVariant,
|
|
707
|
+
variant,
|
|
708
|
+
className: containerClassName,
|
|
709
|
+
children: /* @__PURE__ */ jsx(InputGroup.TextArea, { ...rest, ref, value, onValueChange: setValue })
|
|
710
|
+
}
|
|
711
|
+
);
|
|
712
|
+
};
|
|
713
|
+
|
|
714
|
+
// src/blocks/ColorInput/utils.ts
|
|
715
|
+
var HEX_CHARSET = /^[0-9a-fA-F]+$/;
|
|
716
|
+
var COMPLETE_HEX_PATTERN = /^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
|
|
717
|
+
var MAX_HEX_BODY_LENGTH = 8;
|
|
718
|
+
var PICKER_FALLBACK = "#000000";
|
|
719
|
+
var extractHexBody = (value) => {
|
|
720
|
+
if (typeof value !== "string") return null;
|
|
721
|
+
const trimmed = value.trim();
|
|
722
|
+
if (trimmed === "") return null;
|
|
723
|
+
return trimmed.startsWith("#") ? trimmed.slice(1) : trimmed;
|
|
724
|
+
};
|
|
725
|
+
var isCompleteHexColor = (value) => COMPLETE_HEX_PATTERN.test(value);
|
|
726
|
+
var showPicker = (input) => {
|
|
727
|
+
const isShowPickerSupported = "showPicker" in HTMLInputElement.prototype;
|
|
728
|
+
isShowPickerSupported ? input.showPicker() : input.click();
|
|
729
|
+
};
|
|
730
|
+
var coerceHexInputValue = (value) => {
|
|
731
|
+
const body = extractHexBody(value);
|
|
732
|
+
if (body === null) return "";
|
|
733
|
+
const [validBody] = body.match(/^[0-9a-fA-F]+/) ?? [];
|
|
734
|
+
if (!validBody) return "";
|
|
735
|
+
return `#${validBody.slice(0, MAX_HEX_BODY_LENGTH)}`;
|
|
736
|
+
};
|
|
737
|
+
var coerceColorPickerValue = (value) => {
|
|
738
|
+
const body = extractHexBody(value);
|
|
739
|
+
if (body === null || !HEX_CHARSET.test(body)) return PICKER_FALLBACK;
|
|
740
|
+
if (body.length === 3 || body.length === 4) {
|
|
741
|
+
const [r, g, b] = body;
|
|
742
|
+
return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();
|
|
743
|
+
}
|
|
744
|
+
if (body.length === 6 || body.length === 8) {
|
|
745
|
+
return `#${body.slice(0, 6).toLowerCase()}`;
|
|
746
|
+
}
|
|
747
|
+
return PICKER_FALLBACK;
|
|
748
|
+
};
|
|
749
|
+
var ColorPicker = ({ value, disabled, readOnly, ...props }) => {
|
|
750
|
+
const pickerRef = useRef(null);
|
|
751
|
+
const handleOpenPicker = () => {
|
|
752
|
+
if (!pickerRef.current) return;
|
|
753
|
+
showPicker(pickerRef.current);
|
|
754
|
+
};
|
|
755
|
+
return /* @__PURE__ */ jsxs("div", { className: "tw:relative", children: [
|
|
756
|
+
/* @__PURE__ */ jsx(
|
|
757
|
+
"input",
|
|
758
|
+
{
|
|
759
|
+
...props,
|
|
760
|
+
ref: pickerRef,
|
|
761
|
+
type: "color",
|
|
762
|
+
value: coerceColorPickerValue(value),
|
|
763
|
+
tabIndex: -1,
|
|
764
|
+
"aria-hidden": true,
|
|
765
|
+
className: "tw:pointer-events-none tw:absolute tw:left-0 tw:top-full tw:size-0 tw:opacity-0",
|
|
766
|
+
disabled,
|
|
767
|
+
readOnly
|
|
768
|
+
}
|
|
769
|
+
),
|
|
770
|
+
/* @__PURE__ */ jsx(
|
|
771
|
+
InputGroup.Button,
|
|
772
|
+
{
|
|
773
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
774
|
+
disabled: disabled || readOnly,
|
|
775
|
+
onClick: handleOpenPicker,
|
|
776
|
+
"aria-label": "Pick color",
|
|
777
|
+
children: /* @__PURE__ */ jsx(Pipette, { className: "tw:size-4" })
|
|
778
|
+
}
|
|
779
|
+
)
|
|
780
|
+
] });
|
|
781
|
+
};
|
|
782
|
+
var ColorInput = ({
|
|
783
|
+
ref,
|
|
784
|
+
// group props
|
|
785
|
+
state,
|
|
786
|
+
variant,
|
|
787
|
+
focusVariant,
|
|
788
|
+
sizing,
|
|
789
|
+
className,
|
|
790
|
+
// own props
|
|
791
|
+
value: valueProp,
|
|
792
|
+
onValueChange,
|
|
793
|
+
onValueBlur,
|
|
794
|
+
onChange,
|
|
795
|
+
onBlur,
|
|
796
|
+
defaultValue,
|
|
797
|
+
allowClear = false,
|
|
798
|
+
// input props
|
|
799
|
+
disabled,
|
|
800
|
+
readOnly,
|
|
801
|
+
...restInputProps
|
|
802
|
+
}) => {
|
|
803
|
+
const inputRef = useRef(null);
|
|
804
|
+
const [value, setValue] = useControllableState({
|
|
805
|
+
// A `null` controlled value stays controlled (coerced to ''); `undefined` is uncontrolled.
|
|
806
|
+
prop: valueProp === null ? "" : valueProp,
|
|
807
|
+
defaultProp: defaultValue ?? "",
|
|
808
|
+
onChange: onValueChange
|
|
809
|
+
});
|
|
810
|
+
const isControlled = valueProp !== void 0;
|
|
811
|
+
const canClear = allowClear && !!value && !disabled && !readOnly;
|
|
812
|
+
const swatchColor = coerceHexInputValue(value);
|
|
813
|
+
const isValidSwatch = isCompleteHexColor(swatchColor);
|
|
814
|
+
const handleChange = (event) => {
|
|
815
|
+
setValue(event.target.value);
|
|
816
|
+
onChange?.(event);
|
|
817
|
+
};
|
|
818
|
+
const handleBlur = (event) => {
|
|
819
|
+
const newValue = event.target.value;
|
|
820
|
+
const sanitizedNewValue = coerceHexInputValue(newValue);
|
|
821
|
+
if (sanitizedNewValue !== newValue) {
|
|
822
|
+
if (!isControlled) event.target.value = sanitizedNewValue;
|
|
823
|
+
setValue(sanitizedNewValue);
|
|
824
|
+
}
|
|
825
|
+
onValueBlur?.(sanitizedNewValue);
|
|
826
|
+
onBlur?.(event);
|
|
827
|
+
};
|
|
828
|
+
const handlePickerChange = (event) => {
|
|
829
|
+
setValue(coerceHexInputValue(event.target.value));
|
|
830
|
+
onChange?.(event);
|
|
831
|
+
};
|
|
832
|
+
const handleClear = () => {
|
|
833
|
+
if (!inputRef.current) return;
|
|
834
|
+
inputRef.current.value = "";
|
|
835
|
+
setValue("");
|
|
836
|
+
onChange?.(createChangeInputEvent(inputRef.current));
|
|
837
|
+
};
|
|
838
|
+
return /* @__PURE__ */ jsxs(
|
|
839
|
+
InputGroup,
|
|
840
|
+
{
|
|
841
|
+
state,
|
|
842
|
+
variant,
|
|
843
|
+
sizing,
|
|
844
|
+
focusVariant,
|
|
845
|
+
className,
|
|
846
|
+
children: [
|
|
847
|
+
/* @__PURE__ */ jsx(
|
|
848
|
+
InputGroup.Addon,
|
|
849
|
+
{
|
|
850
|
+
align: "inline-start",
|
|
851
|
+
className: cn(
|
|
852
|
+
{ "tw:-ml-7 tw:opacity-0": !value },
|
|
853
|
+
"tw:transition-[opacity,margin]",
|
|
854
|
+
"tw:ease-linear",
|
|
855
|
+
"tw:duration-200"
|
|
856
|
+
),
|
|
857
|
+
children: /* @__PURE__ */ jsx(
|
|
858
|
+
"div",
|
|
859
|
+
{
|
|
860
|
+
style: isValidSwatch ? { background: swatchColor } : void 0,
|
|
861
|
+
className: cn(
|
|
862
|
+
"tw:size-5",
|
|
863
|
+
"tw:shrink-0",
|
|
864
|
+
"tw:rounded-sm",
|
|
865
|
+
"tw:border",
|
|
866
|
+
"tw:border-solid",
|
|
867
|
+
"tw:border-neutral-300",
|
|
868
|
+
{
|
|
869
|
+
"tw:bg-[linear-gradient(to_top_right,transparent_calc(50%_-_1px),theme(colors.red.300)_calc(50%_-_1px),theme(colors.red.300)_calc(50%_+_1px),transparent_calc(50%_+_1px))]": !isValidSwatch
|
|
870
|
+
}
|
|
871
|
+
)
|
|
872
|
+
}
|
|
873
|
+
)
|
|
874
|
+
}
|
|
875
|
+
),
|
|
876
|
+
/* @__PURE__ */ jsx(
|
|
877
|
+
InputGroup.Input,
|
|
878
|
+
{
|
|
879
|
+
...restInputProps,
|
|
880
|
+
type: "text",
|
|
881
|
+
ref: mergeRefs(ref ?? null, inputRef),
|
|
882
|
+
value,
|
|
883
|
+
onChange: handleChange,
|
|
884
|
+
onBlur: handleBlur,
|
|
885
|
+
disabled,
|
|
886
|
+
readOnly
|
|
887
|
+
}
|
|
888
|
+
),
|
|
889
|
+
/* @__PURE__ */ jsxs(InputGroup.Addon, { align: "inline-end", children: [
|
|
890
|
+
canClear && /* @__PURE__ */ jsx(
|
|
891
|
+
InputGroup.Button,
|
|
892
|
+
{
|
|
893
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
894
|
+
onClick: handleClear,
|
|
895
|
+
"aria-label": "Clear color",
|
|
896
|
+
children: /* @__PURE__ */ jsx(X, { className: "tw:size-4" })
|
|
897
|
+
}
|
|
898
|
+
),
|
|
899
|
+
/* @__PURE__ */ jsx(
|
|
900
|
+
ColorPicker,
|
|
901
|
+
{
|
|
902
|
+
disabled,
|
|
903
|
+
readOnly,
|
|
904
|
+
value,
|
|
905
|
+
onChange: handlePickerChange
|
|
906
|
+
}
|
|
907
|
+
)
|
|
908
|
+
] })
|
|
909
|
+
]
|
|
910
|
+
}
|
|
911
|
+
);
|
|
912
|
+
};
|
|
913
|
+
var toNumberOrNull = (event) => Number.isNaN(event.target.valueAsNumber) ? null : event.target.valueAsNumber;
|
|
914
|
+
var NumberInput = ({
|
|
915
|
+
ref,
|
|
916
|
+
state,
|
|
917
|
+
variant,
|
|
918
|
+
focusVariant,
|
|
919
|
+
sizing,
|
|
920
|
+
className,
|
|
921
|
+
value,
|
|
922
|
+
defaultValue,
|
|
923
|
+
onValueChange,
|
|
924
|
+
onValueBlur,
|
|
925
|
+
onChange,
|
|
926
|
+
onBlur,
|
|
927
|
+
prefix,
|
|
928
|
+
suffix,
|
|
929
|
+
...inputProps
|
|
930
|
+
}) => {
|
|
931
|
+
const handleChange = (event) => {
|
|
932
|
+
onValueChange?.(toNumberOrNull(event));
|
|
933
|
+
onChange?.(event);
|
|
934
|
+
};
|
|
935
|
+
const handleBlur = (event) => {
|
|
936
|
+
onValueBlur?.(toNumberOrNull(event));
|
|
937
|
+
onBlur?.(event);
|
|
938
|
+
};
|
|
939
|
+
const isControlled = value !== void 0;
|
|
940
|
+
const valueProp = isControlled ? { value: value ?? "" } : { defaultValue: defaultValue ?? "" };
|
|
941
|
+
return /* @__PURE__ */ jsxs(
|
|
942
|
+
InputGroup,
|
|
943
|
+
{
|
|
944
|
+
state,
|
|
945
|
+
variant,
|
|
946
|
+
sizing,
|
|
947
|
+
focusVariant,
|
|
948
|
+
className,
|
|
949
|
+
children: [
|
|
950
|
+
prefix && /* @__PURE__ */ jsx(InputGroup.Addon, { align: "inline-start", children: prefix }),
|
|
951
|
+
/* @__PURE__ */ jsx(
|
|
952
|
+
InputGroup.Input,
|
|
953
|
+
{
|
|
954
|
+
...inputProps,
|
|
955
|
+
...valueProp,
|
|
956
|
+
ref,
|
|
957
|
+
type: "number",
|
|
958
|
+
onChange: handleChange,
|
|
959
|
+
onBlur: handleBlur
|
|
960
|
+
}
|
|
961
|
+
),
|
|
962
|
+
suffix && /* @__PURE__ */ jsx(InputGroup.Addon, { align: "inline-end", children: suffix })
|
|
963
|
+
]
|
|
964
|
+
}
|
|
965
|
+
);
|
|
966
|
+
};
|
|
967
|
+
var FormGroupContext = createContext({
|
|
968
|
+
state: "default"
|
|
969
|
+
});
|
|
970
|
+
var FormGroupProvider = FormGroupContext;
|
|
971
|
+
var useFormGroupContext = () => use(FormGroupContext);
|
|
972
|
+
var FormGroupColorInput = ({ ref, ...props }) => {
|
|
973
|
+
const { state } = useFormGroupContext();
|
|
974
|
+
return /* @__PURE__ */ jsx(ColorInput, { state, ...props, ref });
|
|
975
|
+
};
|
|
976
|
+
var toMessage = (entry) => typeof entry === "string" ? entry : entry?.message;
|
|
977
|
+
var FormGroupError = ({ children, className, errors, ...rest }) => {
|
|
978
|
+
const content = useMemo(() => {
|
|
979
|
+
if (children) return children;
|
|
980
|
+
const messages = (errors ?? []).map(toMessage).filter((message) => !!message);
|
|
981
|
+
if (messages.length === 0) return null;
|
|
982
|
+
if (messages.length === 1) return messages[0];
|
|
983
|
+
return /* @__PURE__ */ jsx("ul", { className: "tw:m-0 tw:flex tw:list-disc tw:flex-col tw:gap-0 tw:pl-4", children: messages.map((message, index) => /* @__PURE__ */ jsx("li", { children: message }, index)) });
|
|
984
|
+
}, [children, errors]);
|
|
985
|
+
if (!content) return null;
|
|
986
|
+
return /* @__PURE__ */ jsx("div", { ...rest, role: "alert", className: cn("tw:m-0 tw:text-xs tw:text-destructive", className), children: content });
|
|
987
|
+
};
|
|
988
|
+
var FormGroupHelp = ({ children, ...rest }) => {
|
|
989
|
+
const formGroupContext = useFormGroupContext();
|
|
990
|
+
return /* @__PURE__ */ jsx(HelpBlock, { state: formGroupContext.state === "warning" ? "warning" : "default", ...rest, children });
|
|
991
|
+
};
|
|
992
|
+
var FormGroupNumberInput = ({ ref, ...props }) => {
|
|
993
|
+
const { state } = useFormGroupContext();
|
|
994
|
+
return /* @__PURE__ */ jsx(NumberInput, { ...props, ref, state });
|
|
995
|
+
};
|
|
996
|
+
var FormGroupTextarea = (props) => {
|
|
997
|
+
const { state } = useFormGroupContext();
|
|
998
|
+
return /* @__PURE__ */ jsx(Textarea, { state, ...props });
|
|
999
|
+
};
|
|
1000
|
+
var FormGroupTextInput = ({ ref, ...props }) => {
|
|
1001
|
+
const { state } = useFormGroupContext();
|
|
1002
|
+
return /* @__PURE__ */ jsx(TextInput, { state, ...props, ref });
|
|
1003
|
+
};
|
|
1004
|
+
var FormGroup = ({ className, children, state, ...rest }) => {
|
|
1005
|
+
return /* @__PURE__ */ jsx(FormGroupProvider, { value: { state }, children: /* @__PURE__ */ jsx("div", { ...rest, className: cn("tw:flex tw:flex-col tw:gap-1", className), children }) });
|
|
1006
|
+
};
|
|
1007
|
+
FormGroup.Help = FormGroupHelp;
|
|
1008
|
+
FormGroup.Error = FormGroupError;
|
|
1009
|
+
FormGroup.TextInput = FormGroupTextInput;
|
|
1010
|
+
FormGroup.NumberInput = FormGroupNumberInput;
|
|
1011
|
+
FormGroup.ColorInput = FormGroupColorInput;
|
|
1012
|
+
FormGroup.Textarea = FormGroupTextarea;
|
|
1013
|
+
|
|
1014
|
+
export { ColorInput, FormGroup, InputGroup, Label, NumberInput, ScrollArea, ScrollBar, TextInput, Textarea, createChangeInputEvent, createPrefixedString, mergeRefs, useControllableState };
|
|
1015
|
+
//# sourceMappingURL=chunk-SYIEF644.js.map
|
|
1016
|
+
//# sourceMappingURL=chunk-SYIEF644.js.map
|