@charcoal-ui/react 2.2.1 → 2.4.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.
Files changed (39) hide show
  1. package/dist/components/Checkbox/index.d.ts.map +1 -1
  2. package/dist/components/Checkbox/index.story.d.ts.map +1 -1
  3. package/dist/components/DropdownSelector/DropdownPopover.d.ts +13 -0
  4. package/dist/components/DropdownSelector/DropdownPopover.d.ts.map +1 -0
  5. package/dist/components/DropdownSelector/index.d.ts.map +1 -1
  6. package/dist/components/DropdownSelector/index.story.d.ts +3 -0
  7. package/dist/components/DropdownSelector/index.story.d.ts.map +1 -1
  8. package/dist/components/Modal/index.d.ts +5 -1
  9. package/dist/components/Modal/index.d.ts.map +1 -1
  10. package/dist/core/CharcoalProvider.d.ts +12 -0
  11. package/dist/core/CharcoalProvider.d.ts.map +1 -0
  12. package/dist/core/ComponentAbstraction.d.ts +1 -1
  13. package/dist/core/ComponentAbstraction.d.ts.map +1 -1
  14. package/dist/index.cjs.js +2157 -0
  15. package/dist/index.cjs.js.map +1 -0
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.esm.js +2118 -0
  19. package/dist/index.esm.js.map +1 -0
  20. package/dist/styled.d.ts +3 -3
  21. package/package.json +23 -22
  22. package/src/components/Checkbox/index.story.tsx +29 -11
  23. package/src/components/Checkbox/index.tsx +16 -6
  24. package/src/components/DropdownSelector/DropdownPopover.tsx +72 -0
  25. package/src/components/DropdownSelector/Listbox.tsx +15 -13
  26. package/src/components/DropdownSelector/index.story.tsx +123 -45
  27. package/src/components/DropdownSelector/index.tsx +8 -11
  28. package/src/components/Modal/index.tsx +6 -6
  29. package/src/components/Switch/index.tsx +7 -3
  30. package/src/core/CharcoalProvider.tsx +35 -0
  31. package/src/core/ComponentAbstraction.tsx +1 -1
  32. package/src/index.ts +4 -0
  33. package/dist/components/DropdownSelector/Popover.d.ts +0 -10
  34. package/dist/components/DropdownSelector/Popover.d.ts.map +0 -1
  35. package/dist/index.cjs +0 -4446
  36. package/dist/index.cjs.map +0 -1
  37. package/dist/index.js +0 -4409
  38. package/dist/index.js.map +0 -1
  39. package/src/components/DropdownSelector/Popover.tsx +0 -46
@@ -0,0 +1,2118 @@
1
+ // src/core/ComponentAbstraction.tsx
2
+ import React, { useContext } from "react";
3
+ var DefaultLink = React.forwardRef(
4
+ function DefaultLink2({ to, children, ...rest }, ref) {
5
+ return /* @__PURE__ */ React.createElement("a", { href: to, ref, ...rest }, children);
6
+ }
7
+ );
8
+ var DefaultValue = {
9
+ Link: DefaultLink
10
+ };
11
+ var ComponentAbstractionContext = React.createContext(DefaultValue);
12
+ function ComponentAbstraction({ children, components }) {
13
+ return /* @__PURE__ */ React.createElement(
14
+ ComponentAbstractionContext.Provider,
15
+ {
16
+ value: { ...DefaultValue, ...components }
17
+ },
18
+ children
19
+ );
20
+ }
21
+ function useComponentAbstraction() {
22
+ return useContext(ComponentAbstractionContext);
23
+ }
24
+
25
+ // src/core/SSRProvider.tsx
26
+ import { SSRProvider } from "@react-aria/ssr";
27
+
28
+ // src/core/OverlayProvider.tsx
29
+ import { OverlayProvider } from "@react-aria/overlays";
30
+
31
+ // src/core/CharcoalProvider.tsx
32
+ import React2 from "react";
33
+ import { ThemeProvider } from "styled-components";
34
+ import { TokenInjector } from "@charcoal-ui/styled";
35
+ function CharcoalProvider({
36
+ themeMap,
37
+ defaultTheme = themeMap[":root"],
38
+ components = {},
39
+ injectTokens = true,
40
+ children
41
+ }) {
42
+ return /* @__PURE__ */ React2.createElement(SSRProvider, null, /* @__PURE__ */ React2.createElement(ThemeProvider, { theme: defaultTheme }, injectTokens && /* @__PURE__ */ React2.createElement(TokenInjector, { theme: themeMap }), /* @__PURE__ */ React2.createElement(ComponentAbstraction, { components }, /* @__PURE__ */ React2.createElement(OverlayProvider, null, children))));
43
+ }
44
+
45
+ // src/components/Button/index.tsx
46
+ import React4 from "react";
47
+ import styled3 from "styled-components";
48
+
49
+ // src/_lib/index.ts
50
+ function unreachable(value) {
51
+ throw new Error(
52
+ arguments.length === 0 ? "unreachable" : `unreachable (${JSON.stringify(value)})`
53
+ );
54
+ }
55
+
56
+ // src/styled.ts
57
+ import styled from "styled-components";
58
+ import { createTheme } from "@charcoal-ui/styled";
59
+ var theme = createTheme(styled);
60
+
61
+ // src/components/Clickable/index.tsx
62
+ import React3 from "react";
63
+ import styled2, { css } from "styled-components";
64
+ import { disabledSelector } from "@charcoal-ui/utils";
65
+ var Clickable = React3.forwardRef(
66
+ function Clickable2(props, ref) {
67
+ const { Link } = useComponentAbstraction();
68
+ if ("to" in props) {
69
+ const { onClick, disabled = false, ...rest } = props;
70
+ return /* @__PURE__ */ React3.createElement(
71
+ A,
72
+ {
73
+ ...rest,
74
+ as: disabled ? void 0 : Link,
75
+ onClick: disabled ? void 0 : onClick,
76
+ "aria-disabled": disabled,
77
+ ref
78
+ }
79
+ );
80
+ } else {
81
+ return /* @__PURE__ */ React3.createElement(Button, { ...props, ref });
82
+ }
83
+ }
84
+ );
85
+ var Clickable_default = Clickable;
86
+ var clickableCss = css`
87
+ /* Clickable style */
88
+ cursor: pointer;
89
+
90
+ ${disabledSelector} {
91
+ cursor: default;
92
+ }
93
+ `;
94
+ var Button = styled2.button`
95
+ /* Reset button appearance */
96
+ appearance: none;
97
+ background: transparent;
98
+ padding: 0;
99
+ border-style: none;
100
+ outline: none;
101
+ color: inherit;
102
+ text-rendering: inherit;
103
+ letter-spacing: inherit;
104
+ word-spacing: inherit;
105
+
106
+ &:focus {
107
+ outline: none;
108
+ }
109
+
110
+ /* Change the font styles in all browsers. */
111
+ font: inherit;
112
+
113
+ /* Remove the margin in Firefox and Safari. */
114
+ margin: 0;
115
+
116
+ /* Show the overflow in Edge. */
117
+ overflow: visible;
118
+
119
+ /* Remove the inheritance of text transform in Firefox. */
120
+ text-transform: none;
121
+
122
+ /* Remove the inner border and padding in Firefox. */
123
+ &::-moz-focus-inner {
124
+ border-style: none;
125
+ padding: 0;
126
+ }
127
+
128
+ ${clickableCss}
129
+ `;
130
+ var A = styled2.span`
131
+ /* Reset a-tag appearance */
132
+ color: inherit;
133
+
134
+ &:focus {
135
+ outline: none;
136
+ }
137
+
138
+ .text {
139
+ top: calc(1em + 2em);
140
+ }
141
+
142
+ ${clickableCss}
143
+ `;
144
+
145
+ // src/components/Button/index.tsx
146
+ var Button2 = React4.forwardRef(function Button3({
147
+ children,
148
+ variant = "Default",
149
+ size = "M",
150
+ fixed = false,
151
+ disabled = false,
152
+ ...rest
153
+ }, ref) {
154
+ return /* @__PURE__ */ React4.createElement(
155
+ StyledButton,
156
+ {
157
+ ...rest,
158
+ disabled,
159
+ variant,
160
+ size,
161
+ fixed,
162
+ ref
163
+ },
164
+ children
165
+ );
166
+ });
167
+ var Button_default = Button2;
168
+ var StyledButton = styled3(Clickable_default).withConfig({
169
+ shouldForwardProp(prop) {
170
+ return prop !== "fixed";
171
+ }
172
+ }).attrs(styledProps)`
173
+ width: ${(p) => p.fixed ? "stretch" : "min-content"};
174
+ display: inline-grid;
175
+ align-items: center;
176
+ justify-content: center;
177
+ cursor: pointer;
178
+ user-select: none;
179
+ white-space: nowrap;
180
+
181
+ ${(p) => theme((o) => [
182
+ o.font[p.font].hover.press,
183
+ o.bg[p.background].hover.press,
184
+ o.typography(14).bold.preserveHalfLeading,
185
+ o.padding.horizontal(p.padding),
186
+ o.disabled,
187
+ o.borderRadius("oval"),
188
+ o.outline.default.focus
189
+ ])}
190
+
191
+ /* よく考えたらheight=32って定義が存在しないな... */
192
+ height: ${(p) => p.height}px;
193
+ `;
194
+ function styledProps(props) {
195
+ return {
196
+ ...props,
197
+ ...variantToProps(props.variant),
198
+ ...sizeToProps(props.size)
199
+ };
200
+ }
201
+ function variantToProps(variant) {
202
+ switch (variant) {
203
+ case "Overlay":
204
+ return { font: "text5", background: "surface4" };
205
+ case "Default":
206
+ return { font: "text2", background: "surface3" };
207
+ case "Primary":
208
+ return { font: "text5", background: "brand" };
209
+ case "Navigation":
210
+ return { font: "text5", background: "surface6" };
211
+ case "Danger":
212
+ return { font: "text5", background: "assertive" };
213
+ default:
214
+ return unreachable(variant);
215
+ }
216
+ }
217
+ function sizeToProps(size) {
218
+ switch (size) {
219
+ case "S":
220
+ return {
221
+ height: 32,
222
+ padding: 16
223
+ };
224
+ case "M":
225
+ return {
226
+ height: 40,
227
+ padding: 24
228
+ };
229
+ }
230
+ }
231
+
232
+ // src/components/IconButton/index.tsx
233
+ import React5 from "react";
234
+ import styled4 from "styled-components";
235
+ var IconButton = React5.forwardRef(
236
+ function IconButtonInner({ variant = "Default", size = "M", icon, ...rest }, ref) {
237
+ validateIconSize(size, icon);
238
+ return /* @__PURE__ */ React5.createElement(StyledIconButton, { ...rest, ref, variant, size }, /* @__PURE__ */ React5.createElement("pixiv-icon", { name: icon }));
239
+ }
240
+ );
241
+ var IconButton_default = IconButton;
242
+ var StyledIconButton = styled4(Clickable_default).attrs(styledProps2)`
243
+ user-select: none;
244
+
245
+ width: ${(p) => p.width}px;
246
+ height: ${(p) => p.height}px;
247
+ display: flex;
248
+ align-items: center;
249
+ justify-content: center;
250
+
251
+ ${({ font, background }) => theme((o) => [
252
+ o.font[font],
253
+ o.bg[background].hover.press,
254
+ o.disabled,
255
+ o.borderRadius("oval"),
256
+ o.outline.default.focus
257
+ ])}
258
+ `;
259
+ function styledProps2(props) {
260
+ return {
261
+ ...props,
262
+ ...variantToProps2(props.variant),
263
+ ...sizeToProps2(props.size)
264
+ };
265
+ }
266
+ function variantToProps2(variant) {
267
+ switch (variant) {
268
+ case "Default":
269
+ return { font: "text3", background: "transparent" };
270
+ case "Overlay":
271
+ return { font: "text5", background: "surface4" };
272
+ }
273
+ }
274
+ function sizeToProps2(size) {
275
+ switch (size) {
276
+ case "XS":
277
+ return {
278
+ width: 20,
279
+ height: 20
280
+ };
281
+ case "S":
282
+ return {
283
+ width: 32,
284
+ height: 32
285
+ };
286
+ case "M":
287
+ return {
288
+ width: 40,
289
+ height: 40
290
+ };
291
+ }
292
+ }
293
+ function validateIconSize(size, icon) {
294
+ let requiredIconSize;
295
+ switch (size) {
296
+ case "XS":
297
+ requiredIconSize = "16";
298
+ break;
299
+ case "S":
300
+ case "M":
301
+ requiredIconSize = "24";
302
+ break;
303
+ }
304
+ const result = /^\d*/u.exec(icon);
305
+ if (result == null) {
306
+ throw new Error("Invalid icon name");
307
+ }
308
+ const [iconSize] = result;
309
+ if (iconSize !== requiredIconSize) {
310
+ console.warn(
311
+ `IconButton with size "${size}" expect icon size "${requiredIconSize}, but got "${iconSize}"`
312
+ );
313
+ }
314
+ }
315
+
316
+ // src/components/Radio/index.tsx
317
+ import React6, { useCallback, useContext as useContext2 } from "react";
318
+ import styled5 from "styled-components";
319
+ import warning from "warning";
320
+ import { px } from "@charcoal-ui/utils";
321
+ function Radio({
322
+ value,
323
+ forceChecked = false,
324
+ disabled = false,
325
+ children
326
+ }) {
327
+ const {
328
+ name,
329
+ selected,
330
+ disabled: isParentDisabled,
331
+ readonly,
332
+ hasError,
333
+ onChange
334
+ } = useContext2(RadioGroupContext);
335
+ warning(
336
+ name !== void 0,
337
+ `"name" is not Provided for <Radio>. Perhaps you forgot to wrap with <RadioGroup> ?`
338
+ );
339
+ const isSelected = value === selected;
340
+ const isDisabled = disabled || isParentDisabled;
341
+ const isReadonly = readonly && !isSelected;
342
+ const handleChange = useCallback(
343
+ (e) => {
344
+ onChange(e.currentTarget.value);
345
+ },
346
+ [onChange]
347
+ );
348
+ return /* @__PURE__ */ React6.createElement(RadioRoot, { "aria-disabled": isDisabled || isReadonly }, /* @__PURE__ */ React6.createElement(
349
+ RadioInput,
350
+ {
351
+ name,
352
+ value,
353
+ checked: forceChecked || isSelected,
354
+ hasError,
355
+ onChange: handleChange,
356
+ disabled: isDisabled || isReadonly
357
+ }
358
+ ), children != null && /* @__PURE__ */ React6.createElement(RadioLabel, null, children));
359
+ }
360
+ var RadioRoot = styled5.label`
361
+ display: grid;
362
+ grid-template-columns: auto 1fr;
363
+ grid-gap: ${({ theme: theme4 }) => px(theme4.spacing[4])};
364
+ align-items: center;
365
+ cursor: pointer;
366
+
367
+ ${theme((o) => [o.disabled])}
368
+ `;
369
+ var RadioInput = styled5.input.attrs({ type: "radio" })`
370
+ /** Make prior to browser default style */
371
+ &[type='radio'] {
372
+ appearance: none;
373
+ display: block;
374
+ box-sizing: border-box;
375
+
376
+ margin: 0;
377
+ padding: 6px;
378
+
379
+ width: 20px;
380
+ height: 20px;
381
+
382
+ ${({ hasError = false }) => theme((o) => [
383
+ o.borderRadius("oval"),
384
+ o.bg.surface1.hover.press,
385
+ hasError && o.outline.assertive
386
+ ])};
387
+
388
+ &:not(:checked) {
389
+ border-width: 2px;
390
+ border-style: solid;
391
+ border-color: ${({ theme: theme4 }) => theme4.color.text3};
392
+ }
393
+
394
+ &:checked {
395
+ ${theme((o) => o.bg.brand.hover.press)}
396
+
397
+ &::after {
398
+ content: '';
399
+ display: block;
400
+ width: 8px;
401
+ height: 8px;
402
+ pointer-events: none;
403
+
404
+ ${theme((o) => [o.bg.text5.hover.press, o.borderRadius("oval")])}
405
+ }
406
+ }
407
+
408
+ ${theme((o) => o.outline.default.focus)}
409
+ }
410
+ `;
411
+ var RadioLabel = styled5.div`
412
+ ${theme((o) => [o.typography(14), o.font.text2])}
413
+ `;
414
+ var StyledRadioGroup = styled5.div`
415
+ display: grid;
416
+ grid-template-columns: 1fr;
417
+ grid-gap: ${({ theme: theme4 }) => px(theme4.spacing[8])};
418
+ `;
419
+ var RadioGroupContext = React6.createContext({
420
+ name: void 0,
421
+ selected: void 0,
422
+ disabled: false,
423
+ readonly: false,
424
+ hasError: false,
425
+ onChange() {
426
+ throw new Error(
427
+ "Cannot find onChange() handler. Perhaps you forgot to wrap with <RadioGroup> ?"
428
+ );
429
+ }
430
+ });
431
+ function RadioGroup({
432
+ className,
433
+ value,
434
+ label,
435
+ name,
436
+ onChange,
437
+ disabled,
438
+ readonly,
439
+ hasError,
440
+ children
441
+ }) {
442
+ const handleChange = useCallback(
443
+ (next) => {
444
+ onChange(next);
445
+ },
446
+ [onChange]
447
+ );
448
+ return /* @__PURE__ */ React6.createElement(
449
+ RadioGroupContext.Provider,
450
+ {
451
+ value: {
452
+ name,
453
+ selected: value,
454
+ disabled: disabled ?? false,
455
+ readonly: readonly ?? false,
456
+ hasError: hasError ?? false,
457
+ onChange: handleChange
458
+ }
459
+ },
460
+ /* @__PURE__ */ React6.createElement(
461
+ StyledRadioGroup,
462
+ {
463
+ role: "radiogroup",
464
+ "aria-orientation": "vertical",
465
+ "aria-label": label,
466
+ "aria-invalid": hasError,
467
+ className
468
+ },
469
+ children
470
+ )
471
+ );
472
+ }
473
+
474
+ // src/components/MultiSelect/index.tsx
475
+ import React7, { useCallback as useCallback2, useContext as useContext3 } from "react";
476
+ import styled6, { css as css2 } from "styled-components";
477
+ import warning2 from "warning";
478
+ import { disabledSelector as disabledSelector2, px as px2 } from "@charcoal-ui/utils";
479
+
480
+ // src/components/MultiSelect/context.ts
481
+ import { createContext } from "react";
482
+ var MultiSelectGroupContext = createContext({
483
+ name: void 0,
484
+ selected: [],
485
+ disabled: false,
486
+ readonly: false,
487
+ hasError: false,
488
+ onChange() {
489
+ throw new Error(
490
+ "Cannot find `onChange()` handler. Perhaps you forgot to wrap it with `<MultiSelectGroup />` ?"
491
+ );
492
+ }
493
+ });
494
+
495
+ // src/components/MultiSelect/index.tsx
496
+ function MultiSelect({
497
+ value,
498
+ forceChecked = false,
499
+ disabled = false,
500
+ onChange,
501
+ variant = "default",
502
+ children
503
+ }) {
504
+ const {
505
+ name,
506
+ selected,
507
+ disabled: parentDisabled,
508
+ readonly,
509
+ hasError,
510
+ onChange: parentOnChange
511
+ } = useContext3(MultiSelectGroupContext);
512
+ warning2(
513
+ name !== void 0,
514
+ `"name" is not Provided for <MultiSelect>. Perhaps you forgot to wrap with <MultiSelectGroup> ?`
515
+ );
516
+ const isSelected = selected.includes(value) || forceChecked;
517
+ const isDisabled = disabled || parentDisabled || readonly;
518
+ const handleChange = useCallback2(
519
+ (event) => {
520
+ if (!(event.currentTarget instanceof HTMLInputElement)) {
521
+ return;
522
+ }
523
+ if (onChange)
524
+ onChange({ value, selected: event.currentTarget.checked });
525
+ parentOnChange({ value, selected: event.currentTarget.checked });
526
+ },
527
+ [onChange, parentOnChange, value]
528
+ );
529
+ return /* @__PURE__ */ React7.createElement(MultiSelectRoot, { "aria-disabled": isDisabled }, /* @__PURE__ */ React7.createElement(
530
+ MultiSelectInput,
531
+ {
532
+ ...{
533
+ name,
534
+ value,
535
+ hasError
536
+ },
537
+ checked: isSelected,
538
+ disabled: isDisabled,
539
+ onChange: handleChange,
540
+ overlay: variant === "overlay",
541
+ "aria-invalid": hasError
542
+ }
543
+ ), /* @__PURE__ */ React7.createElement(
544
+ MultiSelectInputOverlay,
545
+ {
546
+ overlay: variant === "overlay",
547
+ hasError,
548
+ "aria-hidden": true
549
+ },
550
+ /* @__PURE__ */ React7.createElement("pixiv-icon", { name: "24/Check", "unsafe-non-guideline-scale": 16 / 24 })
551
+ ), Boolean(children) && /* @__PURE__ */ React7.createElement(MultiSelectLabel, null, children));
552
+ }
553
+ var MultiSelectRoot = styled6.label`
554
+ display: grid;
555
+ grid-template-columns: auto 1fr;
556
+ align-items: center;
557
+ position: relative;
558
+ cursor: pointer;
559
+ ${disabledSelector2} {
560
+ cursor: default;
561
+ }
562
+ gap: ${({ theme: theme4 }) => px2(theme4.spacing[4])};
563
+ ${theme((o) => o.disabled)}
564
+ `;
565
+ var MultiSelectLabel = styled6.div`
566
+ display: flex;
567
+ align-items: center;
568
+ ${theme((o) => [o.typography(14), o.font.text2])}
569
+ `;
570
+ var MultiSelectInput = styled6.input.attrs({ type: "checkbox" })`
571
+ &[type='checkbox'] {
572
+ appearance: none;
573
+ display: block;
574
+ width: 20px;
575
+ height: 20px;
576
+ margin: 0;
577
+
578
+ &:checked {
579
+ ${theme((o) => o.bg.brand.hover.press)}
580
+ }
581
+
582
+ ${({ hasError, overlay }) => theme((o) => [
583
+ o.bg.text3.hover.press,
584
+ o.borderRadius("oval"),
585
+ hasError && !overlay && o.outline.assertive,
586
+ overlay && o.bg.surface4
587
+ ])};
588
+ }
589
+ `;
590
+ var MultiSelectInputOverlay = styled6.div`
591
+ position: absolute;
592
+ top: -2px;
593
+ left: -2px;
594
+ box-sizing: border-box;
595
+ display: flex;
596
+ align-items: center;
597
+ justify-content: center;
598
+
599
+ ${({ hasError, overlay }) => theme((o) => [
600
+ o.width.px(24),
601
+ o.height.px(24),
602
+ o.borderRadius("oval"),
603
+ o.font.text5,
604
+ hasError && overlay && o.outline.assertive
605
+ ])}
606
+
607
+ ${({ overlay }) => overlay && css2`
608
+ border-color: ${({ theme: theme4 }) => theme4.color.text5};
609
+ border-width: 2px;
610
+ border-style: solid;
611
+ `}
612
+ `;
613
+ function MultiSelectGroup({
614
+ className,
615
+ name,
616
+ ariaLabel,
617
+ selected,
618
+ onChange,
619
+ disabled = false,
620
+ readonly = false,
621
+ hasError = false,
622
+ children
623
+ }) {
624
+ const handleChange = useCallback2(
625
+ (payload) => {
626
+ const index = selected.indexOf(payload.value);
627
+ if (payload.selected) {
628
+ if (index < 0) {
629
+ onChange([...selected, payload.value]);
630
+ }
631
+ } else {
632
+ if (index >= 0) {
633
+ onChange([...selected.slice(0, index), ...selected.slice(index + 1)]);
634
+ }
635
+ }
636
+ },
637
+ [onChange, selected]
638
+ );
639
+ return /* @__PURE__ */ React7.createElement(
640
+ MultiSelectGroupContext.Provider,
641
+ {
642
+ value: {
643
+ name,
644
+ selected: Array.from(new Set(selected)),
645
+ disabled,
646
+ readonly,
647
+ hasError,
648
+ onChange: handleChange
649
+ }
650
+ },
651
+ /* @__PURE__ */ React7.createElement(
652
+ "div",
653
+ {
654
+ className,
655
+ "aria-label": ariaLabel,
656
+ "data-testid": "SelectGroup"
657
+ },
658
+ children
659
+ )
660
+ );
661
+ }
662
+
663
+ // src/components/Switch/index.tsx
664
+ import { useSwitch } from "@react-aria/switch";
665
+ import React8, { useRef, useMemo } from "react";
666
+ import { useToggleState } from "react-stately";
667
+ import styled7 from "styled-components";
668
+ import { disabledSelector as disabledSelector3 } from "@charcoal-ui/utils";
669
+ function SwitchCheckbox(props) {
670
+ const { disabled, className } = props;
671
+ const ariaSwitchProps = useMemo(
672
+ () => ({
673
+ ...props,
674
+ "aria-label": "children" in props ? void 0 : props.label,
675
+ isDisabled: props.disabled,
676
+ isSelected: props.checked
677
+ }),
678
+ [props]
679
+ );
680
+ const state = useToggleState(ariaSwitchProps);
681
+ const ref = useRef(null);
682
+ const {
683
+ inputProps: { className: _className, type: _type, ...rest }
684
+ } = useSwitch(ariaSwitchProps, state, ref);
685
+ return /* @__PURE__ */ React8.createElement(Label, { className, "aria-disabled": disabled }, /* @__PURE__ */ React8.createElement(SwitchInput, { ...rest, ref }), "children" in props ? /* @__PURE__ */ React8.createElement(LabelInner, null, props.children) : void 0);
686
+ }
687
+ var Label = styled7.label`
688
+ display: inline-grid;
689
+ grid-template-columns: auto 1fr;
690
+ align-items: center;
691
+ cursor: pointer;
692
+ outline: 0;
693
+
694
+ ${theme((o) => o.disabled)}
695
+
696
+ ${disabledSelector3} {
697
+ cursor: default;
698
+ }
699
+ `;
700
+ var LabelInner = styled7.div`
701
+ ${theme((o) => [
702
+ o.typography(14).preserveHalfLeading,
703
+ o.font.text2,
704
+ o.margin.left(4)
705
+ ])}
706
+ `;
707
+ var SwitchInput = styled7.input.attrs({
708
+ type: "checkbox"
709
+ })`
710
+ &[type='checkbox'] {
711
+ appearance: none;
712
+ display: inline-flex;
713
+ position: relative;
714
+ box-sizing: border-box;
715
+ width: 28px;
716
+ border: 2px solid transparent;
717
+ transition: box-shadow 0.2s, background-color 0.2s;
718
+ cursor: inherit;
719
+ ${theme((o) => [
720
+ o.borderRadius(16),
721
+ o.height.px(16),
722
+ o.bg.text4.hover.press,
723
+ o.outline.default.focus,
724
+ o.margin.all(0)
725
+ ])}
726
+
727
+ &::after {
728
+ content: '';
729
+ position: absolute;
730
+ display: block;
731
+ top: 0;
732
+ left: 0;
733
+ width: 12px;
734
+ height: 12px;
735
+ transform: translateX(0);
736
+ transition: transform 0.2s;
737
+ ${theme((o) => [o.bg.text5.hover.press, o.borderRadius("oval")])}
738
+ }
739
+
740
+ &:checked {
741
+ ${theme((o) => o.bg.brand.hover.press)}
742
+
743
+ &::after {
744
+ transform: translateX(12px);
745
+ }
746
+ }
747
+ }
748
+ `;
749
+
750
+ // src/components/TextField/index.tsx
751
+ import { useTextField } from "@react-aria/textfield";
752
+ import { useVisuallyHidden } from "@react-aria/visually-hidden";
753
+ import React10, {
754
+ useCallback as useCallback3,
755
+ useEffect,
756
+ useRef as useRef2,
757
+ useState
758
+ } from "react";
759
+ import styled9, { css as css3 } from "styled-components";
760
+
761
+ // src/components/FieldLabel/index.tsx
762
+ import React9 from "react";
763
+ import styled8 from "styled-components";
764
+ import { createTheme as createTheme2 } from "@charcoal-ui/styled";
765
+ var FieldLabel = React9.forwardRef(
766
+ function FieldLabel2({
767
+ style,
768
+ className,
769
+ label,
770
+ required = false,
771
+ requiredText,
772
+ subLabel,
773
+ ...labelProps
774
+ }, ref) {
775
+ return /* @__PURE__ */ React9.createElement(FieldLabelWrapper, { style, className }, /* @__PURE__ */ React9.createElement(Label2, { ref, ...labelProps }, label), required && /* @__PURE__ */ React9.createElement(RequiredText, null, requiredText), /* @__PURE__ */ React9.createElement(SubLabelClickable, null, /* @__PURE__ */ React9.createElement("span", null, subLabel)));
776
+ }
777
+ );
778
+ var FieldLabel_default = FieldLabel;
779
+ var theme2 = createTheme2(styled8);
780
+ var Label2 = styled8.label`
781
+ ${theme2((o) => [o.typography(14).bold, o.font.text1])}
782
+ `;
783
+ var RequiredText = styled8.span`
784
+ ${theme2((o) => [o.typography(14), o.font.text3])}
785
+ `;
786
+ var SubLabelClickable = styled8.div`
787
+ ${theme2((o) => [
788
+ o.typography(14),
789
+ o.font.text3.hover.press,
790
+ o.outline.default.focus
791
+ ])}
792
+ `;
793
+ var FieldLabelWrapper = styled8.div`
794
+ display: inline-flex;
795
+ align-items: center;
796
+
797
+ > ${RequiredText} {
798
+ ${theme2((o) => o.margin.left(4))}
799
+ }
800
+
801
+ > ${SubLabelClickable} {
802
+ ${theme2((o) => o.margin.left("auto"))}
803
+ }
804
+ `;
805
+
806
+ // src/components/TextField/index.tsx
807
+ import { createTheme as createTheme3 } from "@charcoal-ui/styled";
808
+ var theme3 = createTheme3(styled9);
809
+ function mergeRefs(...refs) {
810
+ return (value) => {
811
+ for (const ref of refs) {
812
+ if (typeof ref === "function") {
813
+ ref(value);
814
+ } else if (ref !== null) {
815
+ ;
816
+ ref.current = value;
817
+ }
818
+ }
819
+ };
820
+ }
821
+ function countCodePointsInString(string) {
822
+ return Array.from(string).length;
823
+ }
824
+ var TextField = React10.forwardRef(
825
+ function TextField2(props, ref) {
826
+ return props.multiline !== void 0 && props.multiline ? /* @__PURE__ */ React10.createElement(MultiLineTextField, { ref, ...props }) : /* @__PURE__ */ React10.createElement(SingleLineTextField, { ref, ...props });
827
+ }
828
+ );
829
+ var TextField_default = TextField;
830
+ var SingleLineTextField = React10.forwardRef(function SingleLineTextFieldInner({ onChange, ...props }, forwardRef4) {
831
+ const {
832
+ className,
833
+ showLabel = false,
834
+ showCount = false,
835
+ label,
836
+ requiredText,
837
+ subLabel,
838
+ disabled = false,
839
+ required,
840
+ invalid = false,
841
+ assistiveText,
842
+ maxLength,
843
+ prefix = null,
844
+ suffix = null
845
+ } = props;
846
+ const { visuallyHiddenProps } = useVisuallyHidden();
847
+ const ariaRef = useRef2(null);
848
+ const prefixRef = useRef2(null);
849
+ const suffixRef = useRef2(null);
850
+ const [count, setCount] = useState(countCodePointsInString(props.value ?? ""));
851
+ const [prefixWidth, setPrefixWidth] = useState(0);
852
+ const [suffixWidth, setSuffixWidth] = useState(0);
853
+ const nonControlled = props.value === void 0;
854
+ const handleChange = useCallback3(
855
+ (value) => {
856
+ const count2 = countCodePointsInString(value);
857
+ if (maxLength !== void 0 && count2 > maxLength) {
858
+ return;
859
+ }
860
+ if (nonControlled) {
861
+ setCount(count2);
862
+ }
863
+ onChange?.(value);
864
+ },
865
+ [maxLength, nonControlled, onChange]
866
+ );
867
+ useEffect(() => {
868
+ setCount(countCodePointsInString(props.value ?? ""));
869
+ }, [props.value]);
870
+ const { inputProps, labelProps, descriptionProps, errorMessageProps } = useTextField(
871
+ {
872
+ inputElementType: "input",
873
+ isDisabled: disabled,
874
+ isRequired: required,
875
+ validationState: invalid ? "invalid" : "valid",
876
+ description: !invalid && assistiveText,
877
+ errorMessage: invalid && assistiveText,
878
+ onChange: handleChange,
879
+ ...props
880
+ },
881
+ ariaRef
882
+ );
883
+ useEffect(() => {
884
+ const prefixObserver = new ResizeObserver((entries) => {
885
+ setPrefixWidth(entries[0].contentRect.width);
886
+ });
887
+ const suffixObserver = new ResizeObserver((entries) => {
888
+ setSuffixWidth(entries[0].contentRect.width);
889
+ });
890
+ if (prefixRef.current !== null) {
891
+ prefixObserver.observe(prefixRef.current);
892
+ }
893
+ if (suffixRef.current !== null) {
894
+ suffixObserver.observe(suffixRef.current);
895
+ }
896
+ return () => {
897
+ suffixObserver.disconnect();
898
+ prefixObserver.disconnect();
899
+ };
900
+ }, []);
901
+ return /* @__PURE__ */ React10.createElement(TextFieldRoot, { className, isDisabled: disabled }, /* @__PURE__ */ React10.createElement(
902
+ TextFieldLabel,
903
+ {
904
+ label,
905
+ requiredText,
906
+ required,
907
+ subLabel,
908
+ ...labelProps,
909
+ ...!showLabel ? visuallyHiddenProps : {}
910
+ }
911
+ ), /* @__PURE__ */ React10.createElement(StyledInputContainer, null, /* @__PURE__ */ React10.createElement(PrefixContainer, { ref: prefixRef }, /* @__PURE__ */ React10.createElement(Affix, null, prefix)), /* @__PURE__ */ React10.createElement(
912
+ StyledInput,
913
+ {
914
+ ref: mergeRefs(forwardRef4, ariaRef),
915
+ invalid,
916
+ extraLeftPadding: prefixWidth,
917
+ extraRightPadding: suffixWidth,
918
+ ...inputProps
919
+ }
920
+ ), /* @__PURE__ */ React10.createElement(SuffixContainer, { ref: suffixRef }, /* @__PURE__ */ React10.createElement(Affix, null, suffix), showCount && /* @__PURE__ */ React10.createElement(SingleLineCounter, null, maxLength !== void 0 ? `${count}/${maxLength}` : count))), assistiveText != null && assistiveText.length !== 0 && /* @__PURE__ */ React10.createElement(
921
+ AssistiveText,
922
+ {
923
+ invalid,
924
+ ...invalid ? errorMessageProps : descriptionProps
925
+ },
926
+ assistiveText
927
+ ));
928
+ });
929
+ var MultiLineTextField = React10.forwardRef(function MultiLineTextFieldInner({ onChange, ...props }, forwardRef4) {
930
+ const {
931
+ className,
932
+ showCount = false,
933
+ showLabel = false,
934
+ label,
935
+ requiredText,
936
+ subLabel,
937
+ disabled = false,
938
+ required,
939
+ invalid = false,
940
+ assistiveText,
941
+ maxLength,
942
+ autoHeight = false,
943
+ rows: initialRows = 4
944
+ } = props;
945
+ const { visuallyHiddenProps } = useVisuallyHidden();
946
+ const textareaRef = useRef2(null);
947
+ const ariaRef = useRef2(null);
948
+ const [count, setCount] = useState(countCodePointsInString(props.value ?? ""));
949
+ const [rows, setRows] = useState(initialRows);
950
+ const syncHeight = useCallback3(
951
+ (textarea) => {
952
+ const rows2 = (`${textarea.value}
953
+ `.match(/\n/gu)?.length ?? 0) || 1;
954
+ setRows(initialRows <= rows2 ? rows2 : initialRows);
955
+ },
956
+ [initialRows]
957
+ );
958
+ const nonControlled = props.value === void 0;
959
+ const handleChange = useCallback3(
960
+ (value) => {
961
+ const count2 = countCodePointsInString(value);
962
+ if (maxLength !== void 0 && count2 > maxLength) {
963
+ return;
964
+ }
965
+ if (nonControlled) {
966
+ setCount(count2);
967
+ }
968
+ if (autoHeight && textareaRef.current !== null) {
969
+ syncHeight(textareaRef.current);
970
+ }
971
+ onChange?.(value);
972
+ },
973
+ [autoHeight, maxLength, nonControlled, onChange, syncHeight]
974
+ );
975
+ useEffect(() => {
976
+ setCount(countCodePointsInString(props.value ?? ""));
977
+ }, [props.value]);
978
+ const { inputProps, labelProps, descriptionProps, errorMessageProps } = useTextField(
979
+ {
980
+ inputElementType: "textarea",
981
+ isDisabled: disabled,
982
+ isRequired: required,
983
+ validationState: invalid ? "invalid" : "valid",
984
+ description: !invalid && assistiveText,
985
+ errorMessage: invalid && assistiveText,
986
+ onChange: handleChange,
987
+ ...props
988
+ },
989
+ ariaRef
990
+ );
991
+ useEffect(() => {
992
+ if (autoHeight && textareaRef.current !== null) {
993
+ syncHeight(textareaRef.current);
994
+ }
995
+ }, [autoHeight, syncHeight]);
996
+ return /* @__PURE__ */ React10.createElement(TextFieldRoot, { className, isDisabled: disabled }, /* @__PURE__ */ React10.createElement(
997
+ TextFieldLabel,
998
+ {
999
+ label,
1000
+ requiredText,
1001
+ required,
1002
+ subLabel,
1003
+ ...labelProps,
1004
+ ...!showLabel ? visuallyHiddenProps : {}
1005
+ }
1006
+ ), /* @__PURE__ */ React10.createElement(
1007
+ StyledTextareaContainer,
1008
+ {
1009
+ invalid,
1010
+ rows: showCount ? rows + 1 : rows
1011
+ },
1012
+ /* @__PURE__ */ React10.createElement(
1013
+ StyledTextarea,
1014
+ {
1015
+ ref: mergeRefs(textareaRef, forwardRef4, ariaRef),
1016
+ rows,
1017
+ noBottomPadding: showCount,
1018
+ ...inputProps
1019
+ }
1020
+ ),
1021
+ showCount && /* @__PURE__ */ React10.createElement(MultiLineCounter, null, maxLength !== void 0 ? `${count}/${maxLength}` : count)
1022
+ ), assistiveText != null && assistiveText.length !== 0 && /* @__PURE__ */ React10.createElement(
1023
+ AssistiveText,
1024
+ {
1025
+ invalid,
1026
+ ...invalid ? errorMessageProps : descriptionProps
1027
+ },
1028
+ assistiveText
1029
+ ));
1030
+ });
1031
+ var TextFieldRoot = styled9.div`
1032
+ display: flex;
1033
+ flex-direction: column;
1034
+
1035
+ ${(p) => p.isDisabled && { opacity: p.theme.elementEffect.disabled.opacity }}
1036
+ `;
1037
+ var TextFieldLabel = styled9(FieldLabel_default)`
1038
+ ${theme3((o) => o.margin.bottom(8))}
1039
+ `;
1040
+ var StyledInputContainer = styled9.div`
1041
+ height: 40px;
1042
+ display: grid;
1043
+ position: relative;
1044
+ `;
1045
+ var PrefixContainer = styled9.span`
1046
+ position: absolute;
1047
+ top: 50%;
1048
+ left: 8px;
1049
+ transform: translateY(-50%);
1050
+ `;
1051
+ var SuffixContainer = styled9.span`
1052
+ position: absolute;
1053
+ top: 50%;
1054
+ right: 8px;
1055
+ transform: translateY(-50%);
1056
+
1057
+ display: flex;
1058
+ gap: 8px;
1059
+ `;
1060
+ var Affix = styled9.span`
1061
+ user-select: none;
1062
+
1063
+ ${theme3((o) => [o.typography(14).preserveHalfLeading, o.font.text2])}
1064
+ `;
1065
+ var StyledInput = styled9.input`
1066
+ border: none;
1067
+ box-sizing: border-box;
1068
+ outline: none;
1069
+ font-family: inherit;
1070
+
1071
+ /* Prevent zooming for iOS Safari */
1072
+ transform-origin: top left;
1073
+ transform: scale(0.875);
1074
+ width: calc(100% / 0.875);
1075
+ height: calc(100% / 0.875);
1076
+ font-size: calc(14px / 0.875);
1077
+ line-height: calc(22px / 0.875);
1078
+ padding-left: calc((8px + ${(p) => p.extraLeftPadding}px) / 0.875);
1079
+ padding-right: calc((8px + ${(p) => p.extraRightPadding}px) / 0.875);
1080
+ border-radius: calc(4px / 0.875);
1081
+
1082
+ /* Display box-shadow for iOS Safari */
1083
+ appearance: none;
1084
+
1085
+ ${(p) => theme3((o) => [
1086
+ o.bg.surface3.hover,
1087
+ o.outline.default.focus,
1088
+ p.invalid && o.outline.assertive,
1089
+ o.font.text2
1090
+ ])}
1091
+
1092
+ &::placeholder {
1093
+ ${theme3((o) => o.font.text3)}
1094
+ }
1095
+ `;
1096
+ var StyledTextareaContainer = styled9.div`
1097
+ position: relative;
1098
+ overflow: hidden;
1099
+ padding: 0 8px;
1100
+
1101
+ ${(p) => theme3((o) => [
1102
+ o.bg.surface3.hover,
1103
+ p.invalid && o.outline.assertive,
1104
+ o.font.text2,
1105
+ o.borderRadius(4)
1106
+ ])}
1107
+
1108
+ &:focus-within {
1109
+ ${(p) => theme3((o) => p.invalid ? o.outline.assertive : o.outline.default)}
1110
+ }
1111
+
1112
+ ${({ rows }) => css3`
1113
+ height: calc(22px * ${rows} + 18px);
1114
+ `};
1115
+ `;
1116
+ var StyledTextarea = styled9.textarea`
1117
+ border: none;
1118
+ outline: none;
1119
+ resize: none;
1120
+ font-family: inherit;
1121
+ color: inherit;
1122
+
1123
+ /* Prevent zooming for iOS Safari */
1124
+ transform-origin: top left;
1125
+ transform: scale(0.875);
1126
+ width: calc(100% / 0.875);
1127
+ font-size: calc(14px / 0.875);
1128
+ line-height: calc(22px / 0.875);
1129
+ padding: calc(9px / 0.875) 0 ${(p) => p.noBottomPadding ? 0 : ""};
1130
+
1131
+ ${({ rows = 1 }) => css3`
1132
+ height: calc(22px / 0.875 * ${rows});
1133
+ `};
1134
+
1135
+ /* Display box-shadow for iOS Safari */
1136
+ appearance: none;
1137
+
1138
+ background: none;
1139
+
1140
+ &::placeholder {
1141
+ ${theme3((o) => o.font.text3)}
1142
+ }
1143
+
1144
+ /* Hide scrollbar for Chrome, Safari and Opera */
1145
+ &::-webkit-scrollbar {
1146
+ display: none;
1147
+ }
1148
+ /* Hide scrollbar for IE, Edge and Firefox */
1149
+ -ms-overflow-style: none; /* IE and Edge */
1150
+ scrollbar-width: none; /* Firefox */
1151
+ `;
1152
+ var SingleLineCounter = styled9.span`
1153
+ ${theme3((o) => [o.typography(14).preserveHalfLeading, o.font.text3])}
1154
+ `;
1155
+ var MultiLineCounter = styled9.span`
1156
+ position: absolute;
1157
+ bottom: 9px;
1158
+ right: 8px;
1159
+
1160
+ ${theme3((o) => [o.typography(14).preserveHalfLeading, o.font.text3])}
1161
+ `;
1162
+ var AssistiveText = styled9.p`
1163
+ ${(p) => theme3((o) => [
1164
+ o.typography(14),
1165
+ o.margin.top(8),
1166
+ o.margin.bottom(0),
1167
+ o.font[p.invalid ? "assertive" : "text1"]
1168
+ ])}
1169
+ `;
1170
+
1171
+ // src/components/Icon/index.tsx
1172
+ import React11 from "react";
1173
+ import "@charcoal-ui/icons";
1174
+ var Icon = React11.forwardRef(function IconInner({ name, scale, unsafeNonGuidelineScale, className, ...rest }, ref) {
1175
+ return /* @__PURE__ */ React11.createElement(
1176
+ "pixiv-icon",
1177
+ {
1178
+ ref,
1179
+ name,
1180
+ scale,
1181
+ "unsafe-non-guideline-scale": unsafeNonGuidelineScale,
1182
+ class: className,
1183
+ ...rest
1184
+ }
1185
+ );
1186
+ });
1187
+ var Icon_default = Icon;
1188
+
1189
+ // src/components/Modal/index.tsx
1190
+ import React12, { useContext as useContext4, useRef as useRef3 } from "react";
1191
+ import {
1192
+ Overlay,
1193
+ useModalOverlay,
1194
+ useOverlay
1195
+ } from "@react-aria/overlays";
1196
+ import styled10, { css as css4, useTheme } from "styled-components";
1197
+ import { FocusScope } from "@react-aria/focus";
1198
+ import { useDialog } from "@react-aria/dialog";
1199
+
1200
+ // ../foundation/src/grid.ts
1201
+ var COLUMN_UNIT = 80;
1202
+ var GUTTER_UNIT = 24;
1203
+ function columnSystem(span, column, gutter) {
1204
+ return span * column + (span - 1) * gutter;
1205
+ }
1206
+
1207
+ // src/components/Modal/index.tsx
1208
+ import { maxWidth } from "@charcoal-ui/utils";
1209
+ import { useMedia } from "@charcoal-ui/styled";
1210
+ import { animated, useTransition, easings } from "react-spring";
1211
+ var DEFAULT_Z_INDEX = 10;
1212
+ function Modal({
1213
+ children,
1214
+ zIndex = DEFAULT_Z_INDEX,
1215
+ portalContainer,
1216
+ ...props
1217
+ }) {
1218
+ const {
1219
+ title,
1220
+ size = "M",
1221
+ bottomSheet = false,
1222
+ isDismissable,
1223
+ onClose,
1224
+ isOpen = false
1225
+ } = props;
1226
+ const ref = useRef3(null);
1227
+ const { overlayProps, underlayProps } = useOverlay(props, ref);
1228
+ const { modalProps } = useModalOverlay(
1229
+ props,
1230
+ {
1231
+ close: onClose,
1232
+ isOpen,
1233
+ open: () => {
1234
+ },
1235
+ setOpen: () => {
1236
+ },
1237
+ toggle: () => {
1238
+ }
1239
+ },
1240
+ ref
1241
+ );
1242
+ const { dialogProps, titleProps } = useDialog(props, ref);
1243
+ const theme4 = useTheme();
1244
+ const isMobile = useMedia(maxWidth(theme4.breakpoint.screen1)) ?? false;
1245
+ const transitionEnabled = isMobile && bottomSheet !== false;
1246
+ const transition = useTransition(isOpen, {
1247
+ from: {
1248
+ transform: "translateY(100%)",
1249
+ backgroundColor: "rgba(0, 0, 0, 0)"
1250
+ },
1251
+ enter: {
1252
+ transform: "translateY(0%)",
1253
+ backgroundColor: "rgba(0, 0, 0, 0.4)"
1254
+ },
1255
+ leave: {
1256
+ transform: "translateY(100%)",
1257
+ backgroundColor: "rgba(0, 0, 0, 0)"
1258
+ },
1259
+ config: transitionEnabled ? { duration: 400, easing: easings.easeOutQuart } : { duration: 0 }
1260
+ });
1261
+ const showDismiss = !isMobile || bottomSheet !== true;
1262
+ return transition(
1263
+ ({ backgroundColor, transform }, item) => item && /* @__PURE__ */ React12.createElement(Overlay, { portalContainer }, /* @__PURE__ */ React12.createElement(
1264
+ ModalBackground,
1265
+ {
1266
+ zIndex,
1267
+ ...underlayProps,
1268
+ style: transitionEnabled ? { backgroundColor } : {}
1269
+ },
1270
+ /* @__PURE__ */ React12.createElement(FocusScope, { contain: true, restoreFocus: true, autoFocus: true }, /* @__PURE__ */ React12.createElement(
1271
+ ModalDialog,
1272
+ {
1273
+ ref,
1274
+ ...overlayProps,
1275
+ ...modalProps,
1276
+ ...dialogProps,
1277
+ style: transitionEnabled ? { transform } : {},
1278
+ size,
1279
+ bottomSheet
1280
+ },
1281
+ /* @__PURE__ */ React12.createElement(
1282
+ ModalContext.Provider,
1283
+ {
1284
+ value: { titleProps, title, close: onClose, showDismiss }
1285
+ },
1286
+ children,
1287
+ isDismissable === true && /* @__PURE__ */ React12.createElement(
1288
+ ModalCrossButton,
1289
+ {
1290
+ size: "S",
1291
+ icon: "24/Close",
1292
+ onClick: onClose
1293
+ }
1294
+ )
1295
+ )
1296
+ ))
1297
+ ))
1298
+ );
1299
+ }
1300
+ var ModalContext = React12.createContext({
1301
+ titleProps: {},
1302
+ title: "",
1303
+ close: void 0,
1304
+ showDismiss: true
1305
+ });
1306
+ var ModalBackground = animated(styled10.div`
1307
+ z-index: ${({ zIndex }) => zIndex};
1308
+ position: fixed;
1309
+ top: 0;
1310
+ left: 0;
1311
+ width: 100%;
1312
+ height: 100%;
1313
+
1314
+ ${theme((o) => [o.bg.surface4])}
1315
+ `);
1316
+ var ModalDialog = animated(styled10.div`
1317
+ position: absolute;
1318
+ top: 50%;
1319
+ left: 50%;
1320
+ transform: translate(-50%, -50%);
1321
+ width: ${(p) => p.size === "S" ? columnSystem(3, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2 : p.size === "M" ? columnSystem(4, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2 : p.size === "L" ? columnSystem(6, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2 : unreachable(p.size)}px;
1322
+
1323
+ ${theme((o) => [o.bg.background1, o.borderRadius(24)])}
1324
+
1325
+ @media ${({ theme: theme4 }) => maxWidth(theme4.breakpoint.screen1)} {
1326
+ ${(p) => p.bottomSheet === "full" ? css4`
1327
+ top: auto;
1328
+ bottom: 0;
1329
+ left: 0;
1330
+ transform: none;
1331
+ border-radius: 0;
1332
+ width: 100%;
1333
+ height: 100%;
1334
+ ` : p.bottomSheet ? css4`
1335
+ top: auto;
1336
+ bottom: 0;
1337
+ left: 0;
1338
+ transform: none;
1339
+ border-radius: 0;
1340
+ width: 100%;
1341
+ ` : css4`
1342
+ width: calc(100% - 48px);
1343
+ `}
1344
+ }
1345
+ `);
1346
+ var ModalCrossButton = styled10(IconButton_default)`
1347
+ position: absolute;
1348
+ top: 8px;
1349
+ right: 8px;
1350
+
1351
+ ${theme((o) => [o.font.text3.hover.press])}
1352
+ `;
1353
+ function ModalTitle(props) {
1354
+ const { titleProps, title } = useContext4(ModalContext);
1355
+ return /* @__PURE__ */ React12.createElement(ModalHeading, { ...titleProps, ...props }, title);
1356
+ }
1357
+ var ModalHeading = styled10.h3`
1358
+ margin: 0;
1359
+ font-weight: inherit;
1360
+ font-size: inherit;
1361
+ `;
1362
+
1363
+ // src/components/Modal/ModalPlumbing.tsx
1364
+ import React13 from "react";
1365
+ import styled11 from "styled-components";
1366
+ import { maxWidth as maxWidth2 } from "@charcoal-ui/utils";
1367
+ function ModalHeader() {
1368
+ return /* @__PURE__ */ React13.createElement(ModalHeaderRoot, null, /* @__PURE__ */ React13.createElement(StyledModalTitle, null));
1369
+ }
1370
+ var ModalHeaderRoot = styled11.div`
1371
+ height: 64px;
1372
+ display: grid;
1373
+ align-content: center;
1374
+ justify-content: center;
1375
+ `;
1376
+ var StyledModalTitle = styled11(ModalTitle)`
1377
+ ${theme((o) => [o.font.text1, o.typography(16).bold])}
1378
+ `;
1379
+ var ModalAlign = styled11.div`
1380
+ ${theme((o) => [o.padding.horizontal(24)])}
1381
+
1382
+ @media ${({ theme: theme4 }) => maxWidth2(theme4.breakpoint.screen1)} {
1383
+ ${theme((o) => [o.padding.horizontal(16)])}
1384
+ }
1385
+ `;
1386
+ var ModalBody = styled11.div`
1387
+ ${theme((o) => [o.padding.bottom(40)])}
1388
+ `;
1389
+ var ModalButtons = styled11.div`
1390
+ display: grid;
1391
+ grid-auto-flow: row;
1392
+ grid-row-gap: 8px;
1393
+ ${theme((o) => [o.padding.horizontal(24).top(16)])}
1394
+
1395
+ @media ${({ theme: theme4 }) => maxWidth2(theme4.breakpoint.screen1)} {
1396
+ ${theme((o) => [o.padding.horizontal(16)])}
1397
+ }
1398
+ `;
1399
+
1400
+ // src/components/LoadingSpinner/index.tsx
1401
+ import React14, { useImperativeHandle, useRef as useRef4 } from "react";
1402
+ import styled12, { keyframes } from "styled-components";
1403
+ function LoadingSpinner({
1404
+ size = 48,
1405
+ padding = 16,
1406
+ transparent = false
1407
+ }) {
1408
+ return /* @__PURE__ */ React14.createElement(LoadingSpinnerRoot, { size, padding, transparent }, /* @__PURE__ */ React14.createElement(LoadingSpinnerIcon, null));
1409
+ }
1410
+ var LoadingSpinnerRoot = styled12.div.attrs({ role: "progressbar" })`
1411
+ margin: auto;
1412
+ padding: ${(props) => props.padding}px;
1413
+ border-radius: 8px;
1414
+ font-size: ${(props) => props.size}px;
1415
+ width: ${(props) => props.size}px;
1416
+ height: ${(props) => props.size}px;
1417
+ opacity: 0.84;
1418
+ ${({ transparent }) => theme((o) => [
1419
+ o.font.text4,
1420
+ transparent ? o.bg.transparent : o.bg.background1
1421
+ ])}
1422
+ `;
1423
+ var scaleout = keyframes`
1424
+ from {
1425
+ transform: scale(0);
1426
+ opacity: 1;
1427
+ }
1428
+
1429
+ to {
1430
+ transform: scale(1);
1431
+ opacity: 0;
1432
+ }
1433
+ `;
1434
+ var Icon2 = styled12.div.attrs({ role: "presentation" })`
1435
+ width: 1em;
1436
+ height: 1em;
1437
+ border-radius: 1em;
1438
+ background-color: currentColor;
1439
+ animation: ${scaleout} 1s both ease-out;
1440
+ animation-iteration-count: ${(p) => p.once ? 1 : "infinite"};
1441
+
1442
+ &[data-reset-animation] {
1443
+ animation: none;
1444
+ }
1445
+ `;
1446
+ var LoadingSpinnerIcon = React14.forwardRef(function LoadingSpinnerIcon2({ once = false }, ref) {
1447
+ const iconRef = useRef4(null);
1448
+ useImperativeHandle(ref, () => ({
1449
+ restart: () => {
1450
+ if (!iconRef.current) {
1451
+ return;
1452
+ }
1453
+ iconRef.current.dataset.resetAnimation = "true";
1454
+ void iconRef.current.offsetWidth;
1455
+ delete iconRef.current.dataset.resetAnimation;
1456
+ }
1457
+ }));
1458
+ return /* @__PURE__ */ React14.createElement(Icon2, { ref: iconRef, once });
1459
+ });
1460
+
1461
+ // src/components/DropdownSelector/index.tsx
1462
+ import React17, { useMemo as useMemo3, useRef as useRef7 } from "react";
1463
+ import styled15 from "styled-components";
1464
+ import { Item, useSelectState } from "react-stately";
1465
+ import { disabledSelector as disabledSelector4 } from "@charcoal-ui/utils";
1466
+ import { useVisuallyHidden as useVisuallyHidden2 } from "@react-aria/visually-hidden";
1467
+ import { useSelect, HiddenSelect } from "@react-aria/select";
1468
+ import { useButton } from "@react-aria/button";
1469
+
1470
+ // src/components/DropdownSelector/Listbox.tsx
1471
+ import React15, { memo, useRef as useRef5, Fragment, useMemo as useMemo2 } from "react";
1472
+ import styled13 from "styled-components";
1473
+ import { useListBox, useOption } from "@react-aria/listbox";
1474
+ import { mergeProps } from "@react-aria/utils";
1475
+ import { useFocusRing } from "@react-aria/focus";
1476
+ import { px as px3 } from "@charcoal-ui/utils";
1477
+ var Listbox = ({
1478
+ state,
1479
+ mode = "default",
1480
+ ...props
1481
+ }) => {
1482
+ const ref = useRef5(null);
1483
+ const { listBoxProps } = useListBox(props, state, ref);
1484
+ const collection = useMemo2(
1485
+ () => [...state.collection].map((node, index, self) => ({
1486
+ node,
1487
+ first: index === 0,
1488
+ last: index === self.length - 1
1489
+ })),
1490
+ [state.collection]
1491
+ );
1492
+ return /* @__PURE__ */ React15.createElement(ListboxRoot, { ref, ...listBoxProps }, collection.map(({ node, last }) => /* @__PURE__ */ React15.createElement(Fragment, { key: node.key }, /* @__PURE__ */ React15.createElement(Option, { item: node, state, mode }), !last && mode === "separator" && /* @__PURE__ */ React15.createElement(Divider, null))));
1493
+ };
1494
+ var Listbox_default = memo(Listbox);
1495
+ var ListboxRoot = styled13.ul`
1496
+ padding-left: 0;
1497
+ margin: 0;
1498
+ box-sizing: border-box;
1499
+ list-style: none;
1500
+ overflow: auto;
1501
+ max-height: inherit;
1502
+
1503
+ ${theme((o) => [
1504
+ o.bg.background1,
1505
+ o.border.default,
1506
+ o.borderRadius(8),
1507
+ o.outline.default.focus
1508
+ ])}
1509
+ `;
1510
+ var Divider = styled13.div.attrs({ role: "separator" })`
1511
+ display: flex;
1512
+ ${theme((o) => [o.padding.horizontal(8)])}
1513
+
1514
+ &:before {
1515
+ content: '';
1516
+ display: block;
1517
+ width: 100%;
1518
+ height: 1px;
1519
+ background: #00000014;
1520
+ }
1521
+ `;
1522
+ var Option = ({ item, state, mode }) => {
1523
+ const ref = useRef5(null);
1524
+ const { optionProps, isSelected } = useOption(item, state, ref);
1525
+ const { focusProps } = useFocusRing();
1526
+ return /* @__PURE__ */ React15.createElement(OptionRoot, { ...mergeProps(optionProps, focusProps), ref, mode }, isSelected && /* @__PURE__ */ React15.createElement(OptionCheckIcon, { name: "16/Check" }), /* @__PURE__ */ React15.createElement(OptionText, { isSelected }, item.rendered));
1527
+ };
1528
+ var OptionRoot = styled13.li`
1529
+ display: flex;
1530
+ align-items: center;
1531
+ gap: ${({ theme: theme4 }) => px3(theme4.spacing[4])};
1532
+ height: 40px;
1533
+ cursor: pointer;
1534
+ outline: none;
1535
+
1536
+ ${({ mode }) => theme((o) => [
1537
+ o.padding.horizontal(8),
1538
+ mode === "separator" && o.padding.vertical(4)
1539
+ ])}
1540
+
1541
+ &:focus {
1542
+ ${theme((o) => [o.bg.surface3])}
1543
+ }
1544
+ `;
1545
+ var OptionCheckIcon = styled13(Icon_default)`
1546
+ ${theme((o) => [o.font.text2])}
1547
+ `;
1548
+ var OptionText = styled13.span`
1549
+ display: block;
1550
+ ${({ isSelected }) => theme((o) => [
1551
+ o.typography(14),
1552
+ o.font.text2,
1553
+ isSelected ? void 0 : o.margin.left(16),
1554
+ isSelected ? void 0 : o.padding.left(4)
1555
+ ])}
1556
+ `;
1557
+
1558
+ // src/components/DropdownSelector/DropdownPopover.tsx
1559
+ import React16, { useEffect as useEffect2, useRef as useRef6 } from "react";
1560
+ import {
1561
+ DismissButton,
1562
+ Overlay as Overlay2,
1563
+ usePopover
1564
+ } from "@react-aria/overlays";
1565
+ import styled14 from "styled-components";
1566
+ var DropdownPopoverDiv = styled14.div`
1567
+ width: 100%;
1568
+ ${theme((o) => o.margin.top(4).bottom(4))}
1569
+ `;
1570
+ function DropdownPopover({ children, state, ...props }) {
1571
+ const ref = useRef6(null);
1572
+ const { popoverProps, underlayProps } = usePopover(
1573
+ {
1574
+ ...props,
1575
+ popoverRef: ref,
1576
+ containerPadding: 0
1577
+ },
1578
+ state
1579
+ );
1580
+ useEffect2(() => {
1581
+ if (ref.current && props.triggerRef.current) {
1582
+ ref.current.style.width = `${props.triggerRef.current.clientWidth}px`;
1583
+ }
1584
+ }, [props.triggerRef]);
1585
+ useEffect2(() => {
1586
+ if (state.isOpen && props.value !== void 0) {
1587
+ window.requestAnimationFrame(() => {
1588
+ if (props.value === void 0)
1589
+ return;
1590
+ const windowScrollY = window.scrollY;
1591
+ const windowScrollX = window.scrollX;
1592
+ const selectedElement = document.querySelector(
1593
+ `[data-key="${props.value.toString()}"]`
1594
+ );
1595
+ selectedElement?.scrollIntoView({ block: "center" });
1596
+ window.scrollTo(windowScrollX, windowScrollY);
1597
+ });
1598
+ }
1599
+ }, [props.value, state.isOpen]);
1600
+ return /* @__PURE__ */ React16.createElement(Overlay2, null, /* @__PURE__ */ React16.createElement("div", { ...underlayProps, style: { position: "fixed", inset: 0 } }), /* @__PURE__ */ React16.createElement(DropdownPopoverDiv, { ...popoverProps, ref }, /* @__PURE__ */ React16.createElement(DismissButton, { onDismiss: () => state.close() }), children, /* @__PURE__ */ React16.createElement(DismissButton, { onDismiss: () => state.close() })));
1601
+ }
1602
+
1603
+ // src/components/DropdownSelector/index.tsx
1604
+ var DropdownSelector = ({
1605
+ open,
1606
+ className,
1607
+ label = "",
1608
+ requiredText = "",
1609
+ subLabel,
1610
+ assertiveText,
1611
+ autoComplete,
1612
+ invalid = false,
1613
+ disabled = false,
1614
+ required = false,
1615
+ showLabel = false,
1616
+ mode = "default",
1617
+ ...props
1618
+ }) => {
1619
+ const { visuallyHiddenProps } = useVisuallyHidden2();
1620
+ const triggerRef = useRef7(null);
1621
+ const selectProps = useMemo3(
1622
+ () => ({
1623
+ ...props,
1624
+ label,
1625
+ isOpen: open,
1626
+ isDisabled: disabled,
1627
+ isRequired: required,
1628
+ errorMessage: invalid && assertiveText,
1629
+ validationState: invalid ? "invalid" : "valid",
1630
+ onSelectionChange: props.onChange,
1631
+ selectedKey: props.value,
1632
+ defaultSelectedKey: props.defaultValue
1633
+ }),
1634
+ [assertiveText, disabled, invalid, label, open, props, required]
1635
+ );
1636
+ const state = useSelectState(selectProps);
1637
+ const {
1638
+ labelProps,
1639
+ triggerProps,
1640
+ valueProps,
1641
+ menuProps,
1642
+ errorMessageProps,
1643
+ descriptionProps
1644
+ } = useSelect(selectProps, state, triggerRef);
1645
+ const { buttonProps } = useButton(triggerProps, triggerRef);
1646
+ const hasAssertiveText = assertiveText !== void 0 && assertiveText.length > 0;
1647
+ return /* @__PURE__ */ React17.createElement(DropdownSelectorRoot, { "aria-disabled": disabled, className }, /* @__PURE__ */ React17.createElement(
1648
+ DropdownFieldLabel,
1649
+ {
1650
+ label,
1651
+ required,
1652
+ requiredText,
1653
+ subLabel,
1654
+ ...labelProps,
1655
+ ...!showLabel ? visuallyHiddenProps : {}
1656
+ }
1657
+ ), /* @__PURE__ */ React17.createElement(
1658
+ HiddenSelect,
1659
+ {
1660
+ state,
1661
+ triggerRef,
1662
+ label,
1663
+ name: props.name,
1664
+ isDisabled: disabled,
1665
+ autoComplete
1666
+ }
1667
+ ), /* @__PURE__ */ React17.createElement(DropdownButtonWrapper, null, /* @__PURE__ */ React17.createElement(DropdownButton, { ...buttonProps, ref: triggerRef, invalid }, /* @__PURE__ */ React17.createElement(DropdownButtonText, { ...valueProps }, state.selectedItem ? state.selectedItem.rendered : props.placeholder), /* @__PURE__ */ React17.createElement(DropdownButtonIcon, { name: "16/Menu" })), state.isOpen && /* @__PURE__ */ React17.createElement(
1668
+ DropdownPopover,
1669
+ {
1670
+ state,
1671
+ triggerRef,
1672
+ value: props.value ?? props.defaultValue
1673
+ },
1674
+ /* @__PURE__ */ React17.createElement(Listbox_default, { ...menuProps, state, mode })
1675
+ )), hasAssertiveText && /* @__PURE__ */ React17.createElement(
1676
+ AssertiveText,
1677
+ {
1678
+ invalid,
1679
+ ...invalid ? errorMessageProps : descriptionProps
1680
+ },
1681
+ assertiveText
1682
+ ));
1683
+ };
1684
+ var DropdownSelector_default = DropdownSelector;
1685
+ var DropdownSelectorItem = Item;
1686
+ var DropdownSelectorRoot = styled15.div`
1687
+ position: relative;
1688
+ display: inline-block;
1689
+ width: 100%;
1690
+
1691
+ ${disabledSelector4} {
1692
+ cursor: default;
1693
+ ${theme((o) => o.disabled)}
1694
+ }
1695
+ `;
1696
+ var DropdownFieldLabel = styled15(FieldLabel_default)`
1697
+ width: 100%;
1698
+
1699
+ ${theme((o) => o.margin.bottom(8))}
1700
+ `;
1701
+ var DropdownButtonWrapper = styled15.div`
1702
+ position: relative;
1703
+ `;
1704
+ var DropdownButton = styled15.button`
1705
+ display: flex;
1706
+ justify-content: space-between;
1707
+ align-items: center;
1708
+
1709
+ height: 40px;
1710
+ width: 100%;
1711
+ box-sizing: border-box;
1712
+ cursor: pointer;
1713
+
1714
+ ${disabledSelector4} {
1715
+ cursor: default;
1716
+ }
1717
+
1718
+ ${({ invalid }) => theme((o) => [
1719
+ o.border.default,
1720
+ o.padding.horizontal(8),
1721
+ o.outline.default.focus,
1722
+ o.bg.surface3,
1723
+ o.borderRadius(4),
1724
+ invalid && o.outline.assertive
1725
+ ])}
1726
+ `;
1727
+ var DropdownButtonText = styled15.span`
1728
+ text-align: left;
1729
+
1730
+ ${theme((o) => [o.typography(14), o.font.text2])}
1731
+ `;
1732
+ var DropdownButtonIcon = styled15(Icon_default)`
1733
+ ${theme((o) => [o.font.text2])}
1734
+ `;
1735
+ var AssertiveText = styled15.div`
1736
+ ${({ invalid }) => theme((o) => [
1737
+ o.typography(14),
1738
+ o.margin.top(8),
1739
+ invalid ? o.font.assertive : o.font.text2
1740
+ ])}
1741
+ `;
1742
+
1743
+ // src/components/SegmentedControl/index.tsx
1744
+ import React19, { forwardRef, memo as memo2, useMemo as useMemo4, useRef as useRef8 } from "react";
1745
+ import { useRadioGroupState } from "react-stately";
1746
+ import {
1747
+ useRadio,
1748
+ useRadioGroup
1749
+ } from "@react-aria/radio";
1750
+ import styled16 from "styled-components";
1751
+ import { disabledSelector as disabledSelector5 } from "@charcoal-ui/utils";
1752
+
1753
+ // src/components/SegmentedControl/RadioGroupContext.tsx
1754
+ import React18, { createContext as createContext2, useContext as useContext5 } from "react";
1755
+ var RadioContext = createContext2(null);
1756
+ var RadioProvider = ({
1757
+ value,
1758
+ children
1759
+ }) => {
1760
+ return /* @__PURE__ */ React18.createElement(RadioContext.Provider, { value }, children);
1761
+ };
1762
+ var useRadioContext = () => {
1763
+ const state = useContext5(RadioContext);
1764
+ if (state === null)
1765
+ throw new Error("`<RadioProvider>` is not likely mounted.");
1766
+ return state;
1767
+ };
1768
+
1769
+ // src/components/SegmentedControl/index.tsx
1770
+ var SegmentedControl = forwardRef(
1771
+ function SegmentedControlInner(props, ref) {
1772
+ const ariaRadioGroupProps = useMemo4(
1773
+ () => ({
1774
+ ...props,
1775
+ isDisabled: props.disabled,
1776
+ isReadOnly: props.readonly,
1777
+ isRequired: props.required
1778
+ }),
1779
+ [props]
1780
+ );
1781
+ const state = useRadioGroupState(ariaRadioGroupProps);
1782
+ const { radioGroupProps } = useRadioGroup(ariaRadioGroupProps, state);
1783
+ const segmentedControlItems = useMemo4(() => {
1784
+ return props.data.map(
1785
+ (d) => typeof d === "string" ? { value: d, label: d } : d
1786
+ );
1787
+ }, [props.data]);
1788
+ return /* @__PURE__ */ React19.createElement(SegmentedControlRoot, { ref, ...radioGroupProps }, /* @__PURE__ */ React19.createElement(RadioProvider, { value: state }, segmentedControlItems.map((item) => /* @__PURE__ */ React19.createElement(
1789
+ Segmented,
1790
+ {
1791
+ key: item.value,
1792
+ value: item.value,
1793
+ disabled: item.disabled
1794
+ },
1795
+ item.label
1796
+ ))));
1797
+ }
1798
+ );
1799
+ var SegmentedControl_default = memo2(SegmentedControl);
1800
+ var Segmented = ({ children, ...props }) => {
1801
+ const state = useRadioContext();
1802
+ const ref = useRef8(null);
1803
+ const ariaRadioProps = useMemo4(
1804
+ () => ({ ...props, isDisabled: props.disabled }),
1805
+ [props]
1806
+ );
1807
+ const { inputProps, isDisabled, isSelected } = useRadio(
1808
+ ariaRadioProps,
1809
+ state,
1810
+ ref
1811
+ );
1812
+ return /* @__PURE__ */ React19.createElement(
1813
+ SegmentedRoot,
1814
+ {
1815
+ "aria-disabled": isDisabled || state.isReadOnly,
1816
+ checked: isSelected
1817
+ },
1818
+ /* @__PURE__ */ React19.createElement(SegmentedInput, { ...inputProps, ref }),
1819
+ /* @__PURE__ */ React19.createElement(RadioLabel2, null, /* @__PURE__ */ React19.createElement(SegmentedLabelInner, null, children))
1820
+ );
1821
+ };
1822
+ var SegmentedControlRoot = styled16.div`
1823
+ display: inline-flex;
1824
+ align-items: center;
1825
+
1826
+ ${theme((o) => [o.bg.surface3, o.borderRadius(16)])}
1827
+ `;
1828
+ var SegmentedRoot = styled16.label`
1829
+ position: relative;
1830
+ display: flex;
1831
+ align-items: center;
1832
+ cursor: pointer;
1833
+ height: 32px;
1834
+
1835
+ ${disabledSelector5} {
1836
+ cursor: default;
1837
+ }
1838
+
1839
+ ${({ checked }) => theme((o) => [
1840
+ o.padding.horizontal(16),
1841
+ o.borderRadius(16),
1842
+ o.disabled,
1843
+ checked === true && o.bg.brand,
1844
+ checked === true ? o.font.text5 : o.font.text2
1845
+ ])}
1846
+ `;
1847
+ var SegmentedInput = styled16.input`
1848
+ position: absolute;
1849
+
1850
+ height: 0px;
1851
+ width: 0px;
1852
+ padding: 0;
1853
+ margin: 0;
1854
+
1855
+ appearance: none;
1856
+ box-sizing: border-box;
1857
+ overflow: hidden;
1858
+ white-space: nowrap;
1859
+ opacity: 0;
1860
+ `;
1861
+ var RadioLabel2 = styled16.div`
1862
+ background: transparent;
1863
+ display: flex;
1864
+ align-items: center;
1865
+ height: 22px;
1866
+ `;
1867
+ var SegmentedLabelInner = styled16.div`
1868
+ ${theme((o) => [o.typography(14)])}
1869
+ `;
1870
+
1871
+ // src/components/Checkbox/index.tsx
1872
+ import React20, { forwardRef as forwardRef2, memo as memo3, useMemo as useMemo5 } from "react";
1873
+ import styled17, { css as css5 } from "styled-components";
1874
+ import { useCheckbox } from "@react-aria/checkbox";
1875
+ import { useObjectRef } from "@react-aria/utils";
1876
+ import { useToggleState as useToggleState2 } from "react-stately";
1877
+ import { disabledSelector as disabledSelector6, px as px4 } from "@charcoal-ui/utils";
1878
+ var Checkbox = forwardRef2(
1879
+ function CheckboxInner(props, ref) {
1880
+ const ariaCheckboxProps = useMemo5(
1881
+ () => ({
1882
+ ...props,
1883
+ isSelected: props.checked,
1884
+ defaultSelected: props.defaultChecked,
1885
+ "aria-label": "children" in props ? void 0 : props.label,
1886
+ isDisabled: props.disabled
1887
+ }),
1888
+ [props]
1889
+ );
1890
+ const state = useToggleState2(ariaCheckboxProps);
1891
+ const objectRef = useObjectRef(ref);
1892
+ const { inputProps } = useCheckbox(ariaCheckboxProps, state, objectRef);
1893
+ const isDisabled = (props.disabled ?? false) || (props.readonly ?? false);
1894
+ return /* @__PURE__ */ React20.createElement(InputRoot, { "aria-disabled": isDisabled }, /* @__PURE__ */ React20.createElement(CheckboxRoot, null, /* @__PURE__ */ React20.createElement(CheckboxInput, { type: "checkbox", ...inputProps }), /* @__PURE__ */ React20.createElement(CheckboxInputOverlay, { "aria-hidden": true, checked: inputProps.checked }, /* @__PURE__ */ React20.createElement(Icon_default, { name: "24/Check", unsafeNonGuidelineScale: 2 / 3 }))), "children" in props && /* @__PURE__ */ React20.createElement(InputLabel, null, props.children));
1895
+ }
1896
+ );
1897
+ var Checkbox_default = memo3(Checkbox);
1898
+ var hiddenCss = css5`
1899
+ visibility: hidden;
1900
+ `;
1901
+ var InputRoot = styled17.label`
1902
+ position: relative;
1903
+ display: flex;
1904
+
1905
+ cursor: pointer;
1906
+ ${disabledSelector6} {
1907
+ cursor: default;
1908
+ }
1909
+
1910
+ gap: ${({ theme: theme4 }) => px4(theme4.spacing[4])};
1911
+ ${theme((o) => [o.disabled])}
1912
+ `;
1913
+ var CheckboxRoot = styled17.div`
1914
+ position: relative;
1915
+ `;
1916
+ var CheckboxInput = styled17.input`
1917
+ &[type='checkbox'] {
1918
+ appearance: none;
1919
+ display: block;
1920
+ cursor: pointer;
1921
+ margin: 0;
1922
+ width: 20px;
1923
+ height: 20px;
1924
+
1925
+ &:checked {
1926
+ ${theme((o) => o.bg.brand.hover.press)}
1927
+ }
1928
+ &:not(:checked) {
1929
+ border-width: 2px;
1930
+ border-style: solid;
1931
+ border-color: ${({ theme: theme4 }) => theme4.color.text4};
1932
+ }
1933
+ ${theme((o) => [o.outline.default.focus, o.borderRadius(4)])}
1934
+ }
1935
+ `;
1936
+ var CheckboxInputOverlay = styled17.div`
1937
+ position: absolute;
1938
+ top: -2px;
1939
+ left: -2px;
1940
+ box-sizing: border-box;
1941
+ display: flex;
1942
+ align-items: center;
1943
+ justify-content: center;
1944
+
1945
+ ${theme((o) => [o.width.px(24), o.height.px(24), o.font.text5])}
1946
+
1947
+ ${({ checked }) => checked !== true && hiddenCss};
1948
+ `;
1949
+ var InputLabel = styled17.div`
1950
+ ${theme((o) => [o.font.text2])}
1951
+
1952
+ font-size: 14px;
1953
+ /** checkbox の height が 20px なのでcheckbox と text が揃っているように見せるために行ボックスの高さを 20px にしている */
1954
+ line-height: 20px;
1955
+ `;
1956
+
1957
+ // src/components/TagItem/index.tsx
1958
+ import React21, {
1959
+ forwardRef as forwardRef3,
1960
+ memo as memo4,
1961
+ useMemo as useMemo6
1962
+ } from "react";
1963
+ import { useObjectRef as useObjectRef2 } from "@react-aria/utils";
1964
+ import styled18, { css as css6 } from "styled-components";
1965
+ import { disabledSelector as disabledSelector7, px as px5 } from "@charcoal-ui/utils";
1966
+ import { useButton as useButton2 } from "@react-aria/button";
1967
+ var sizeMap = {
1968
+ S: 32,
1969
+ M: 40
1970
+ };
1971
+ var TagItem = forwardRef3(
1972
+ function TagItemInner({
1973
+ label,
1974
+ translatedLabel,
1975
+ bgColor = "#7ACCB1",
1976
+ bgImage,
1977
+ size = "M",
1978
+ disabled,
1979
+ status = "default",
1980
+ ...props
1981
+ }, _ref) {
1982
+ const ref = useObjectRef2(_ref);
1983
+ const ariaButtonProps = useMemo6(
1984
+ () => ({
1985
+ elementType: "a",
1986
+ isDisabled: disabled,
1987
+ ...props
1988
+ }),
1989
+ [disabled, props]
1990
+ );
1991
+ const { buttonProps } = useButton2(ariaButtonProps, ref);
1992
+ const hasTranslatedLabel = translatedLabel !== void 0 && translatedLabel.length > 0;
1993
+ return /* @__PURE__ */ React21.createElement(
1994
+ TagItemRoot,
1995
+ {
1996
+ ref,
1997
+ size: hasTranslatedLabel ? "M" : size,
1998
+ status,
1999
+ ...buttonProps
2000
+ },
2001
+ /* @__PURE__ */ React21.createElement(Background, { bgColor, bgImage }),
2002
+ /* @__PURE__ */ React21.createElement(Inner, null, /* @__PURE__ */ React21.createElement(LabelWrapper, { isTranslate: hasTranslatedLabel }, hasTranslatedLabel && /* @__PURE__ */ React21.createElement(TranslatedLabel, null, /* @__PURE__ */ React21.createElement(Label3, null, translatedLabel)), /* @__PURE__ */ React21.createElement(Label3, null, label)), status === "active" && /* @__PURE__ */ React21.createElement(Icon_default, { name: "16/Remove" }))
2003
+ );
2004
+ }
2005
+ );
2006
+ var TagItem_default = memo4(TagItem);
2007
+ var TagItemRoot = styled18.a`
2008
+ isolation: isolate;
2009
+ position: relative;
2010
+ height: ${({ size }) => sizeMap[size]}px;
2011
+ display: inline-flex;
2012
+ align-items: center;
2013
+ justify-content: center;
2014
+ text-decoration: none;
2015
+ cursor: pointer;
2016
+ overflow: hidden;
2017
+
2018
+ ${({ size, status }) => theme((o) => [
2019
+ o.outline.default.focus,
2020
+ o.borderRadius(4),
2021
+ status !== "active" && size === "M" && o.padding.horizontal(24),
2022
+ status !== "active" && size === "S" && o.padding.horizontal(16),
2023
+ status === "inactive" && o.bg.surface3,
2024
+ status === "inactive" ? o.font.text2 : o.font.text5,
2025
+ ...status === "active" ? [o.padding.left(16), o.padding.right(8)] : []
2026
+ ])}
2027
+
2028
+ ${disabledSelector7} {
2029
+ ${theme((o) => [o.disabled])}
2030
+ cursor: default;
2031
+ }
2032
+ `;
2033
+ var Background = styled18.div`
2034
+ position: absolute;
2035
+ z-index: 1;
2036
+ top: 0;
2037
+ left: 0;
2038
+ width: 100%;
2039
+ height: 100%;
2040
+
2041
+ background-color: ${({ bgColor }) => bgColor};
2042
+
2043
+ ${({ bgImage }) => bgImage !== void 0 && css6`
2044
+ ${theme((o) => [o.bg.surface4])}
2045
+ &::before {
2046
+ content: '';
2047
+ position: absolute;
2048
+ top: 0;
2049
+ left: 0;
2050
+ width: 100%;
2051
+ height: 100%;
2052
+ background-position: center;
2053
+ background-size: cover;
2054
+ background-image: url(${bgImage});
2055
+ mix-blend-mode: overlay;
2056
+ }
2057
+ `}
2058
+ `;
2059
+ var Inner = styled18.div`
2060
+ display: inline-flex;
2061
+ gap: ${({ theme: theme4 }) => px5(theme4.spacing[8])};
2062
+ align-items: center;
2063
+ z-index: 2;
2064
+ `;
2065
+ var labelCSS = css6`
2066
+ ${theme((o) => [o.typography(14).bold])}
2067
+ `;
2068
+ var translateLabelCSS = css6`
2069
+ display: flex;
2070
+ align-items: center;
2071
+ flex-direction: column;
2072
+ font-size: 10px;
2073
+ `;
2074
+ var LabelWrapper = styled18.div`
2075
+ ${({ isTranslate }) => isTranslate ?? false ? translateLabelCSS : labelCSS}
2076
+ `;
2077
+ var Label3 = styled18.span`
2078
+ max-width: 152px;
2079
+ overflow: hidden;
2080
+ text-overflow: ellipsis;
2081
+ white-space: nowrap;
2082
+ font-size: inherit;
2083
+ color: inherit;
2084
+ line-height: inherit;
2085
+ `;
2086
+ var TranslatedLabel = styled18.div`
2087
+ ${theme((o) => [o.typography(12).bold])}
2088
+ `;
2089
+ export {
2090
+ Button_default as Button,
2091
+ CharcoalProvider,
2092
+ Checkbox_default as Checkbox,
2093
+ Clickable_default as Clickable,
2094
+ ComponentAbstraction,
2095
+ DropdownSelector_default as DropdownSelector,
2096
+ DropdownSelectorItem,
2097
+ Icon_default as Icon,
2098
+ IconButton_default as IconButton,
2099
+ LoadingSpinner,
2100
+ LoadingSpinnerIcon,
2101
+ Modal,
2102
+ ModalAlign,
2103
+ ModalBody,
2104
+ ModalButtons,
2105
+ ModalHeader,
2106
+ MultiSelect,
2107
+ MultiSelectGroup,
2108
+ OverlayProvider,
2109
+ Radio,
2110
+ RadioGroup,
2111
+ SSRProvider,
2112
+ SegmentedControl_default as SegmentedControl,
2113
+ SwitchCheckbox as Switch,
2114
+ TagItem_default as TagItem,
2115
+ TextField_default as TextField,
2116
+ useComponentAbstraction
2117
+ };
2118
+ //# sourceMappingURL=index.esm.js.map