@exem-ui/react 0.3.4-next.20260727012122 → 0.3.4-next.20260728024650

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.
@@ -1,12 +1,13 @@
1
- import { ChevronDown, Check } from './chunk-GWP7YKJP.mjs';
1
+ import { ChevronDown, Search, Check } from './chunk-GWP7YKJP.mjs';
2
2
  import { cva, cn } from '@exem-ui/core/utils';
3
3
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
5
- import * as TabsPrimitive2 from '@radix-ui/react-tabs';
5
+ import { Combobox as Combobox$1 } from '@base-ui/react/combobox';
6
6
  import * as React from 'react';
7
7
  import { createContext, forwardRef, useId, useContext, createElement, useRef, useState } from 'react';
8
- import * as SelectPrimitive from '@radix-ui/react-select';
9
8
  import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
9
+ import * as TabsPrimitive2 from '@radix-ui/react-tabs';
10
+ import * as SelectPrimitive from '@radix-ui/react-select';
10
11
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
11
12
 
12
13
  var colorPaletteColorClasses = {
@@ -121,166 +122,6 @@ function FlatColorPalette({
121
122
  return /* @__PURE__ */ jsx(ColorPalette, { ...rootProps, children: palette.map((color) => /* @__PURE__ */ jsx(ColorPalette.Swatch, { color }, color)) });
122
123
  }
123
124
  FlatColorPalette.displayName = "FlatColorPalette";
124
- var segmentListVariants = cva(
125
- "inline-flex items-center overflow-hidden rounded-medium bg-elevation-elevation-2",
126
- {
127
- variants: {
128
- size: {
129
- small: "h-7 gap-0 p-0.5",
130
- medium: "h-8 gap-0 p-0.5",
131
- large: "h-10 gap-0 p-0.5"
132
- }
133
- },
134
- defaultVariants: {
135
- size: "medium"
136
- }
137
- }
138
- );
139
- var segmentItemVariants = cva(
140
- [
141
- "flex flex-1 items-center justify-center rounded-weak",
142
- "focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring",
143
- "disabled:cursor-not-allowed",
144
- "data-[state=active]:bg-component-segmentedOption data-[state=active]:text-text-primary data-[state=active]:shadow-weak",
145
- "data-[state=inactive]:text-text-tertiary data-[state=inactive]:disabled:text-text-disabled",
146
- "transition-colors duration-200 ease-in-out"
147
- ],
148
- {
149
- variants: {
150
- size: {
151
- small: "h-6 gap-0.5 text-body-3 font-medium",
152
- medium: "h-7 gap-1 text-body-2 font-medium",
153
- large: "h-9 gap-1.5 text-body-2 font-medium"
154
- }
155
- },
156
- defaultVariants: {
157
- size: "medium"
158
- }
159
- }
160
- );
161
- var segmentIconVariants = cva("flex items-center justify-center", {
162
- variants: {
163
- size: {
164
- small: "size-4",
165
- medium: "size-4",
166
- large: "size-5"
167
- }
168
- },
169
- defaultVariants: {
170
- size: "medium"
171
- }
172
- });
173
- var SegmentContext = createContext(void 0);
174
- var useSegmentContext = () => {
175
- const context = useContext(SegmentContext);
176
- if (!context) {
177
- throw new Error("Segment components must be used within a Segment");
178
- }
179
- return context;
180
- };
181
- var Segment = forwardRef(
182
- ({ size = "medium", children, ...props }, ref) => /* @__PURE__ */ jsx(SegmentContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx(TabsPrimitive2.Root, { ref, ...props, children }) })
183
- );
184
- Segment.List = forwardRef(
185
- ({ className, ...props }, ref) => {
186
- const { size } = useSegmentContext();
187
- return /* @__PURE__ */ jsx(
188
- TabsPrimitive2.List,
189
- {
190
- ref,
191
- className: cn(segmentListVariants({ size }), className),
192
- ...props
193
- }
194
- );
195
- }
196
- );
197
- Segment.Item = forwardRef(
198
- ({ className, leftIcon, children, ...props }, ref) => {
199
- const { size } = useSegmentContext();
200
- return /* @__PURE__ */ jsxs(
201
- TabsPrimitive2.Trigger,
202
- {
203
- ref,
204
- className: cn(segmentItemVariants({ size }), className),
205
- ...props,
206
- children: [
207
- leftIcon && /* @__PURE__ */ jsx("span", { className: cn(segmentIconVariants({ size })), children: leftIcon }),
208
- /* @__PURE__ */ jsx("span", { className: "flex items-center", children })
209
- ]
210
- }
211
- );
212
- }
213
- );
214
- Segment.Content = forwardRef(
215
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
216
- TabsPrimitive2.Content,
217
- {
218
- ref,
219
- className: cn(
220
- "ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
221
- className
222
- ),
223
- ...props
224
- }
225
- )
226
- );
227
- Segment.displayName = "Segment";
228
- Segment.List.displayName = "Segment.List";
229
- Segment.Content.displayName = "Segment.Content";
230
- Segment.Item.displayName = "Segment.Item";
231
- function FlatSegment({
232
- items,
233
- disabled,
234
- className,
235
- ...props
236
- }) {
237
- const rootProps = props;
238
- return /* @__PURE__ */ jsx(Segment, { ...rootProps, children: /* @__PURE__ */ jsx(Segment.List, { className, children: items.map((item) => /* @__PURE__ */ createElement(Segment.Item, { ...item, key: item.value, disabled: disabled || item.disabled })) }) });
239
- }
240
- FlatSegment.displayName = "FlatSegment";
241
- var overlayListVariants = {
242
- content: cn(
243
- "relative z-50 min-w-[8rem] overflow-hidden rounded-medium border border-border-primary bg-background-overlay shadow-weak",
244
- "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
245
- ),
246
- viewport: cn("flex flex-col gap-0.5 p-1"),
247
- item: cva(
248
- "relative flex w-full gap-0.5 cursor-pointer select-none items-center rounded-weak px-2 text-body-2 text-text-primary outline-none hover:bg-elevation-elevation-2 data-[disabled]:pointer-events-none data-[disabled]:text-text-disabled",
249
- {
250
- defaultVariants: { size: "medium" },
251
- variants: {
252
- size: {
253
- xsmall: "h-6",
254
- small: "h-7",
255
- medium: "h-8",
256
- large: "h-10"
257
- }
258
- }
259
- }
260
- ),
261
- itemText: cva("truncate flex items-center flex-1 min-w-0", {
262
- defaultVariants: { size: "medium" },
263
- variants: {
264
- size: {
265
- xsmall: "h-6",
266
- small: "h-7",
267
- medium: "h-8",
268
- large: "h-10"
269
- }
270
- }
271
- }),
272
- slotSize: cva("shrink-0 flex items-center justify-center text-icon-primary", {
273
- defaultVariants: { size: "medium" },
274
- variants: {
275
- size: {
276
- xsmall: "size-4",
277
- small: "size-4",
278
- medium: "size-4",
279
- large: "size-5"
280
- }
281
- }
282
- })
283
- };
284
125
  function ScrollBar({
285
126
  className,
286
127
  orientation = "vertical",
@@ -351,6 +192,49 @@ function ScrollArea({
351
192
  }
352
193
  );
353
194
  }
195
+ var overlayListVariants = {
196
+ content: cn(
197
+ "relative z-50 min-w-[8rem] overflow-hidden rounded-medium border border-border-primary bg-background-overlay shadow-weak",
198
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95"
199
+ ),
200
+ viewport: cn("flex flex-col gap-0.5 p-1"),
201
+ item: cva(
202
+ "relative flex w-full gap-0.5 cursor-pointer select-none items-center rounded-weak px-2 text-body-2 text-text-primary outline-none hover:bg-elevation-elevation-2 data-[disabled]:pointer-events-none data-[disabled]:text-text-disabled",
203
+ {
204
+ defaultVariants: { size: "medium" },
205
+ variants: {
206
+ size: {
207
+ xsmall: "h-6",
208
+ small: "h-7",
209
+ medium: "h-8",
210
+ large: "h-10"
211
+ }
212
+ }
213
+ }
214
+ ),
215
+ itemText: cva("truncate flex items-center flex-1 min-w-0", {
216
+ defaultVariants: { size: "medium" },
217
+ variants: {
218
+ size: {
219
+ xsmall: "h-6",
220
+ small: "h-7",
221
+ medium: "h-8",
222
+ large: "h-10"
223
+ }
224
+ }
225
+ }),
226
+ slotSize: cva("shrink-0 flex items-center justify-center text-icon-primary", {
227
+ defaultVariants: { size: "medium" },
228
+ variants: {
229
+ size: {
230
+ xsmall: "size-4",
231
+ small: "size-4",
232
+ medium: "size-4",
233
+ large: "size-5"
234
+ }
235
+ }
236
+ })
237
+ };
354
238
  var commonInputVariants = {
355
239
  // Container variants - 전체 컴포넌트 래퍼
356
240
  container: cva("flex flex-col"),
@@ -510,6 +394,593 @@ var selectVariants = {
510
394
  }),
511
395
  viewport: overlayListVariants.viewport
512
396
  };
397
+ var textFieldVariants = {
398
+ container: commonInputVariants.container,
399
+ label: commonInputVariants.label,
400
+ wrapper: cva(
401
+ "flex w-full flex-row items-center rounded-medium border transition-colors focus-within:border-border-focused focus-within:outline-none",
402
+ {
403
+ variants: {
404
+ variant: {
405
+ fill: "border-transparent bg-elevation-elevation-2",
406
+ line: "border-border-primary",
407
+ lineBackground: "border-border-primary bg-background-primary"
408
+ },
409
+ size: {
410
+ xsmall: "h-6 gap-0 px-1",
411
+ small: "h-7 gap-0.5 px-1.5",
412
+ medium: "h-8 gap-0.5 px-2",
413
+ large: "h-10 gap-1 px-2.5"
414
+ },
415
+ state: {
416
+ default: "text-text-primary",
417
+ error: "text-text-primary",
418
+ disabled: "cursor-not-allowed text-text-disabled"
419
+ }
420
+ },
421
+ compoundVariants: [
422
+ { variant: "fill", state: "error", class: "border-border-critical" },
423
+ {
424
+ variant: "fill",
425
+ state: "disabled",
426
+ class: "bg-elevation-elevation-2 border-transparent"
427
+ },
428
+ { variant: "line", state: "error", class: "border-border-critical" },
429
+ { variant: "line", state: "disabled", class: "border-border-primary" },
430
+ { variant: "lineBackground", state: "error", class: "border-border-critical" },
431
+ { variant: "lineBackground", state: "disabled", class: "border-border-primary" }
432
+ ],
433
+ defaultVariants: { variant: "fill", size: "medium", state: "default" }
434
+ }
435
+ ),
436
+ input: cva(
437
+ "w-full border-none bg-transparent p-0 focus:outline-none focus:ring-0 disabled:cursor-not-allowed",
438
+ {
439
+ variants: {
440
+ size: {
441
+ xsmall: "text-body-3 placeholder:text-body-3",
442
+ small: "text-body-2 placeholder:text-body-2",
443
+ medium: "text-body-2 placeholder:text-body-2",
444
+ large: "text-body-1 placeholder:text-body-1"
445
+ },
446
+ state: {
447
+ default: "text-text-primary placeholder:text-text-tertiary",
448
+ error: "text-text-primary placeholder:text-text-tertiary",
449
+ disabled: "text-text-disabled placeholder:text-text-disabled"
450
+ }
451
+ },
452
+ defaultVariants: { size: "medium", state: "default" }
453
+ }
454
+ ),
455
+ description: cva("mt-0.5 font-regular text-text-tertiary", {
456
+ variants: {
457
+ size: {
458
+ xsmall: "text-caption",
459
+ small: "text-body-3",
460
+ medium: "text-body-3",
461
+ large: "text-body-2"
462
+ },
463
+ error: {
464
+ true: "text-text-critical",
465
+ false: ""
466
+ },
467
+ disabled: {
468
+ true: "text-text-disabled",
469
+ false: ""
470
+ }
471
+ },
472
+ compoundVariants: [
473
+ {
474
+ disabled: true,
475
+ error: true,
476
+ class: "text-text-disabled"
477
+ // disabled가 error보다 우선
478
+ }
479
+ ],
480
+ defaultVariants: { size: "medium", error: false, disabled: false }
481
+ }),
482
+ subText: cva("ml-1 shrink-0 font-regular", {
483
+ variants: {
484
+ size: {
485
+ xsmall: "text-body-3",
486
+ small: "text-body-2",
487
+ medium: "text-body-2",
488
+ large: "text-body-1"
489
+ },
490
+ disabled: {
491
+ true: "text-text-disabled",
492
+ false: "text-text-tertiary"
493
+ }
494
+ },
495
+ defaultVariants: { size: "medium", disabled: false }
496
+ }),
497
+ icon: cva("shrink-0 text-icon-tertiary", {
498
+ variants: {
499
+ size: {
500
+ xsmall: "size-4",
501
+ small: "size-4",
502
+ medium: "size-4",
503
+ large: "size-5"
504
+ }
505
+ },
506
+ defaultVariants: { size: "medium" }
507
+ })
508
+ };
509
+
510
+ // src/combobox/comboboxVariants.ts
511
+ var comboboxVariants = {
512
+ container: selectVariants.container,
513
+ description: selectVariants.description,
514
+ iconSize: overlayListVariants.slotSize,
515
+ label: selectVariants.label,
516
+ // 단독(anchored) 입력형 - Select 트리거와 같은 fill 박스 형태
517
+ input: cva(
518
+ "w-full rounded-medium bg-elevation-elevation-2 text-text-primary outline-none placeholder:text-text-tertiary focus:ring-1 focus:ring-inset focus:ring-border-focused disabled:cursor-not-allowed disabled:bg-elevation-elevation-2 disabled:text-text-disabled",
519
+ {
520
+ defaultVariants: { size: "medium" },
521
+ variants: {
522
+ size: {
523
+ xsmall: "h-6 px-[4px] text-body-3",
524
+ small: "h-7 px-[6px] text-body-2",
525
+ medium: "h-8 px-[8px] text-body-2",
526
+ large: "h-10 px-[10px] text-body-1"
527
+ }
528
+ }
529
+ }
530
+ ),
531
+ item: (props) => cn(
532
+ overlayListVariants.item(props),
533
+ // group/option: 표시 전용 체크박스가 아이템의 data-selected 상태를 CSS로 읽기 위함
534
+ "group/option data-[highlighted]:bg-elevation-elevation-2 data-[selected]:bg-elevation-accent-0"
535
+ ),
536
+ // 다중 선택 아이템의 표시 전용 체크박스 (Figma: 16px, gap 6px — item gap 2px + mr 4px)
537
+ // 시각은 Checkbox 컴포넌트의 상태 토큰과 동일하게 유지한다
538
+ itemCheckbox: cn(
539
+ "mr-1 flex size-4 shrink-0 items-center justify-center rounded-weak border border-border-secondary bg-background-primary transition-colors duration-200",
540
+ "group-data-[selected]/option:border-transparent group-data-[selected]/option:bg-solid-accent-default",
541
+ "group-data-[disabled]/option:bg-elevation-elevation-3"
542
+ ),
543
+ list: cn(overlayListVariants.viewport, "p-0 empty:hidden"),
544
+ // Positioner는 transform으로 자체 스타킹 컨텍스트를 만들므로 z-index를 여기(루트 레벨)에 줘야
545
+ // Modal/Sheet(z-50) 위에 팝업이 올라온다. popup의 z-50은 컨텍스트 내부라 루트에선 무효.
546
+ // pointer-events-auto: radix modal이 body에 pointer-events:none을 걸어도 팝업 클릭이 동작하도록.
547
+ // TODO(#305): radix 제거(Base UI 이관) 시 pointer-events-auto는 불필요 (z-50은 유지)
548
+ positioner: "z-50 pointer-events-auto",
549
+ popup: cn(
550
+ "relative z-50 flex max-h-[var(--available-height)] w-[var(--anchor-width)] min-w-[8rem] max-w-[var(--available-width)] origin-[var(--transform-origin)] flex-col gap-0.5 overflow-hidden rounded-medium border border-border-primary bg-background-overlay p-1 shadow-weak",
551
+ "transition-[transform,scale,opacity] duration-150 data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[starting-style]:scale-95 data-[starting-style]:opacity-0"
552
+ ),
553
+ // 팝업 상단 검색바 - TextField(fill)와 동일한 디자인
554
+ searchIcon: textFieldVariants.icon,
555
+ searchInput: textFieldVariants.input,
556
+ searchWrapper: textFieldVariants.wrapper,
557
+ trigger: (props) => cn(
558
+ // selectVariants.trigger의 radix용 data-[state=open] 클래스는 Base UI에서 매칭되지 않는
559
+ // dead class로 남는다(무해). 아래는 동일한 open 스타일의 Base UI attribute 버전.
560
+ selectVariants.trigger(props),
561
+ "data-[popup-open]:border data-[popup-open]:border-border-focused"
562
+ )
563
+ };
564
+ var ComboboxContext = createContext(null);
565
+ var useComboboxContext = () => useContext(ComboboxContext);
566
+ function ComboboxRoot({
567
+ size = "medium",
568
+ error = false,
569
+ disabled = false,
570
+ className,
571
+ ...props
572
+ }) {
573
+ return /* @__PURE__ */ jsx(ComboboxContext.Provider, { value: { disabled, error, multiple: Boolean(props.multiple), size }, children: /* @__PURE__ */ jsx("div", { className: cn(comboboxVariants.container(), className), children: /* @__PURE__ */ jsx(Combobox$1.Root, { disabled, ...props }) }) });
574
+ }
575
+ function ComboboxLabel({
576
+ className,
577
+ size: sizeProp,
578
+ required = false,
579
+ ...props
580
+ }) {
581
+ const context = useComboboxContext();
582
+ const size = sizeProp ?? context?.size;
583
+ const disabled = context?.disabled ?? false;
584
+ return /* @__PURE__ */ jsx(
585
+ Combobox$1.Label,
586
+ {
587
+ "data-slot": "combobox-label",
588
+ className: cn(comboboxVariants.label({ disabled, required, size }), className),
589
+ ...props
590
+ }
591
+ );
592
+ }
593
+ function ComboboxDescription({ children, size: sizeProp, className }) {
594
+ const context = useComboboxContext();
595
+ const size = sizeProp ?? context?.size;
596
+ if (!children) {
597
+ return null;
598
+ }
599
+ return /* @__PURE__ */ jsx(
600
+ "div",
601
+ {
602
+ "data-slot": "combobox-description",
603
+ className: cn(
604
+ comboboxVariants.description({
605
+ disabled: context?.disabled ?? false,
606
+ error: context?.error ?? false,
607
+ size
608
+ }),
609
+ className
610
+ ),
611
+ children: /* @__PURE__ */ jsx("p", { children })
612
+ }
613
+ );
614
+ }
615
+ function ComboboxValue(props) {
616
+ return /* @__PURE__ */ jsx(Combobox$1.Value, { "data-slot": "combobox-value", ...props });
617
+ }
618
+ function ComboboxTrigger({
619
+ className,
620
+ children,
621
+ size: sizeProp,
622
+ variant = "fill",
623
+ error: errorProp,
624
+ ...props
625
+ }) {
626
+ const context = useComboboxContext();
627
+ const size = sizeProp ?? context?.size ?? "medium";
628
+ const error = errorProp ?? context?.error ?? false;
629
+ return /* @__PURE__ */ jsxs(
630
+ Combobox$1.Trigger,
631
+ {
632
+ "data-slot": "combobox-trigger",
633
+ className: cn(comboboxVariants.trigger({ error, size, variant }), className),
634
+ ...props,
635
+ children: [
636
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 truncate text-left", children }),
637
+ /* @__PURE__ */ jsx(
638
+ ChevronDown,
639
+ {
640
+ type: "regular",
641
+ className: cn(
642
+ comboboxVariants.iconSize({ size }),
643
+ "transition-transform duration-200 group-data-[popup-open]:rotate-180 group-disabled:text-icon-disabled"
644
+ )
645
+ }
646
+ )
647
+ ]
648
+ }
649
+ );
650
+ }
651
+ function ComboboxInput({ className, size: sizeProp, ...props }) {
652
+ const context = useComboboxContext();
653
+ const size = sizeProp ?? context?.size ?? "medium";
654
+ return /* @__PURE__ */ jsx(
655
+ Combobox$1.Input,
656
+ {
657
+ "data-slot": "combobox-input",
658
+ className: cn(comboboxVariants.input({ size }), className),
659
+ ...props
660
+ }
661
+ );
662
+ }
663
+ function ComboboxSearch({ className, size: sizeProp, ...props }) {
664
+ const context = useComboboxContext();
665
+ const size = sizeProp ?? context?.size ?? "medium";
666
+ return (
667
+ // Figma Select List 스펙: 팝업 p-1(4px) 안에 Search 래퍼 p-1이 중첩되어 검색바 인셋은 8px
668
+ /* @__PURE__ */ jsx("div", { "data-slot": "combobox-search", className: "w-full shrink-0 p-1", children: /* @__PURE__ */ jsxs("div", { className: cn(comboboxVariants.searchWrapper({ size, variant: "fill" }), className), children: [
669
+ /* @__PURE__ */ jsx(
670
+ Search,
671
+ {
672
+ type: "regular",
673
+ className: cn("flex items-center justify-center", comboboxVariants.searchIcon({ size }))
674
+ }
675
+ ),
676
+ /* @__PURE__ */ jsx(
677
+ Combobox$1.Input,
678
+ {
679
+ "data-slot": "combobox-search-input",
680
+ className: cn("px-0.5", comboboxVariants.searchInput({ size })),
681
+ ...props
682
+ }
683
+ )
684
+ ] }) })
685
+ );
686
+ }
687
+ function ComboboxContent({
688
+ className,
689
+ children,
690
+ sideOffset = 4,
691
+ align = "start",
692
+ side,
693
+ ...props
694
+ }) {
695
+ return /* @__PURE__ */ jsx(Combobox$1.Portal, { children: /* @__PURE__ */ jsx(
696
+ Combobox$1.Positioner,
697
+ {
698
+ className: comboboxVariants.positioner,
699
+ align,
700
+ side,
701
+ sideOffset,
702
+ children: /* @__PURE__ */ jsx(
703
+ Combobox$1.Popup,
704
+ {
705
+ "data-slot": "combobox-content",
706
+ className: cn(comboboxVariants.popup, className),
707
+ ...props,
708
+ children
709
+ }
710
+ )
711
+ }
712
+ ) });
713
+ }
714
+ function ComboboxList({ className, ...props }) {
715
+ return (
716
+ // min-h-0: 팝업(max-h: --available-height)이 좁을 때 flex 자식인 ScrollArea가 줄어들도록
717
+ /* @__PURE__ */ jsx(
718
+ ScrollArea,
719
+ {
720
+ className: "min-h-0 max-h-60 [&_[data-slot=scroll-area-viewport]]:max-h-[inherit]",
721
+ disableHorizontalScroll: true,
722
+ children: /* @__PURE__ */ jsx(
723
+ Combobox$1.List,
724
+ {
725
+ "data-slot": "combobox-list",
726
+ className: cn(comboboxVariants.list, className),
727
+ ...props
728
+ }
729
+ )
730
+ }
731
+ )
732
+ );
733
+ }
734
+ function ComboboxItem({
735
+ className,
736
+ children,
737
+ size: sizeProp,
738
+ checkbox,
739
+ leftIcon,
740
+ rightIcon,
741
+ rightSlot,
742
+ ...props
743
+ }) {
744
+ const context = useComboboxContext();
745
+ const size = sizeProp ?? context?.size ?? "medium";
746
+ const showCheckbox = checkbox ?? context?.multiple ?? false;
747
+ return /* @__PURE__ */ jsxs(
748
+ Combobox$1.Item,
749
+ {
750
+ "data-slot": "combobox-item",
751
+ className: cn(comboboxVariants.item({ size }), className),
752
+ ...props,
753
+ children: [
754
+ showCheckbox && // 표시 전용 체크박스 — 선택 상태는 아이템의 data-selected가 CSS로 구동 (Figma 14009-5969)
755
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: comboboxVariants.itemCheckbox, children: /* @__PURE__ */ jsx(
756
+ Check,
757
+ {
758
+ type: "regular",
759
+ className: "hidden size-4 text-icon-static-light group-data-[selected]/option:block"
760
+ }
761
+ ) }),
762
+ leftIcon && /* @__PURE__ */ jsx("div", { className: comboboxVariants.iconSize({ size }), children: leftIcon }),
763
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-1 overflow-hidden", children: [
764
+ /* @__PURE__ */ jsx(
765
+ "span",
766
+ {
767
+ className: "min-w-0 flex-1 truncate",
768
+ title: typeof children === "string" ? children : void 0,
769
+ children
770
+ }
771
+ ),
772
+ rightSlot && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: rightSlot })
773
+ ] }),
774
+ rightIcon && /* @__PURE__ */ jsx("div", { className: comboboxVariants.iconSize({ size }), children: rightIcon })
775
+ ]
776
+ }
777
+ );
778
+ }
779
+ function ComboboxEmpty({ className, children = "No data", ...props }) {
780
+ return /* @__PURE__ */ jsx(
781
+ Combobox$1.Empty,
782
+ {
783
+ "data-slot": "combobox-empty",
784
+ className: cn(
785
+ // Base UI Empty는 live region이라 display:none으로 숨기면 안 됨 → 결과가 있을 땐 크기만 0으로 수축
786
+ // Figma 스펙: empty 팝업 높이 80px 고정 (팝업 패딩 4px*2 포함이므로 72px)
787
+ "flex items-center justify-center text-body-2 text-text-disabled",
788
+ "[&:not(:empty)]:min-h-[72px] [&:not(:empty)]:p-2",
789
+ className
790
+ ),
791
+ ...props,
792
+ children
793
+ }
794
+ );
795
+ }
796
+ var Combobox = Object.assign(ComboboxRoot, {
797
+ Content: ComboboxContent,
798
+ Description: ComboboxDescription,
799
+ Empty: ComboboxEmpty,
800
+ Input: ComboboxInput,
801
+ Item: ComboboxItem,
802
+ Label: ComboboxLabel,
803
+ List: ComboboxList,
804
+ Search: ComboboxSearch,
805
+ Trigger: ComboboxTrigger,
806
+ Value: ComboboxValue
807
+ });
808
+ function FlatCombobox({
809
+ options,
810
+ placeholder,
811
+ searchPlaceholder,
812
+ emptyText,
813
+ label,
814
+ required,
815
+ description,
816
+ size,
817
+ variant,
818
+ error,
819
+ disabled,
820
+ value,
821
+ defaultValue,
822
+ onValueChange,
823
+ onOpenChange,
824
+ className,
825
+ listClassName
826
+ }) {
827
+ const resolveOption = (v) => options.find((option) => option.value === v) ?? null;
828
+ return /* @__PURE__ */ jsxs(
829
+ Combobox,
830
+ {
831
+ items: options,
832
+ itemToStringLabel: (option) => option.label,
833
+ isItemEqualToValue: (a, b) => a?.value === b?.value,
834
+ value: value !== void 0 ? resolveOption(value) : void 0,
835
+ defaultValue: defaultValue !== void 0 ? resolveOption(defaultValue) : void 0,
836
+ onValueChange: (option) => onValueChange?.(option?.value ?? null),
837
+ onOpenChange,
838
+ size,
839
+ error,
840
+ disabled,
841
+ className,
842
+ children: [
843
+ label && /* @__PURE__ */ jsx(Combobox.Label, { required, children: label }),
844
+ /* @__PURE__ */ jsx(Combobox.Trigger, { variant, children: /* @__PURE__ */ jsx(Combobox.Value, { placeholder }) }),
845
+ /* @__PURE__ */ jsxs(Combobox.Content, { children: [
846
+ /* @__PURE__ */ jsx(Combobox.Search, { placeholder: searchPlaceholder }),
847
+ /* @__PURE__ */ jsx(Combobox.Empty, { children: emptyText }),
848
+ /* @__PURE__ */ jsx(Combobox.List, { className: listClassName, children: (option) => /* @__PURE__ */ jsx(
849
+ Combobox.Item,
850
+ {
851
+ value: option,
852
+ disabled: option.disabled,
853
+ leftIcon: option.leftIcon,
854
+ rightIcon: option.rightIcon,
855
+ rightSlot: option.rightSlot,
856
+ children: option.label
857
+ },
858
+ option.value
859
+ ) })
860
+ ] }),
861
+ description && /* @__PURE__ */ jsx(Combobox.Description, { children: description })
862
+ ]
863
+ }
864
+ );
865
+ }
866
+ FlatCombobox.displayName = "FlatCombobox";
867
+ var segmentListVariants = cva(
868
+ "inline-flex items-center overflow-hidden rounded-medium bg-elevation-elevation-2",
869
+ {
870
+ variants: {
871
+ size: {
872
+ small: "h-7 gap-0 p-0.5",
873
+ medium: "h-8 gap-0 p-0.5",
874
+ large: "h-10 gap-0 p-0.5"
875
+ }
876
+ },
877
+ defaultVariants: {
878
+ size: "medium"
879
+ }
880
+ }
881
+ );
882
+ var segmentItemVariants = cva(
883
+ [
884
+ "flex flex-1 items-center justify-center rounded-weak",
885
+ "focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-ring",
886
+ "disabled:cursor-not-allowed",
887
+ "data-[state=active]:bg-component-segmentedOption data-[state=active]:text-text-primary data-[state=active]:shadow-weak",
888
+ "data-[state=inactive]:text-text-tertiary data-[state=inactive]:disabled:text-text-disabled",
889
+ "transition-colors duration-200 ease-in-out"
890
+ ],
891
+ {
892
+ variants: {
893
+ size: {
894
+ small: "h-6 gap-0.5 text-body-3 font-medium",
895
+ medium: "h-7 gap-1 text-body-2 font-medium",
896
+ large: "h-9 gap-1.5 text-body-2 font-medium"
897
+ }
898
+ },
899
+ defaultVariants: {
900
+ size: "medium"
901
+ }
902
+ }
903
+ );
904
+ var segmentIconVariants = cva("flex items-center justify-center", {
905
+ variants: {
906
+ size: {
907
+ small: "size-4",
908
+ medium: "size-4",
909
+ large: "size-5"
910
+ }
911
+ },
912
+ defaultVariants: {
913
+ size: "medium"
914
+ }
915
+ });
916
+ var SegmentContext = createContext(void 0);
917
+ var useSegmentContext = () => {
918
+ const context = useContext(SegmentContext);
919
+ if (!context) {
920
+ throw new Error("Segment components must be used within a Segment");
921
+ }
922
+ return context;
923
+ };
924
+ var Segment = forwardRef(
925
+ ({ size = "medium", children, ...props }, ref) => /* @__PURE__ */ jsx(SegmentContext.Provider, { value: { size }, children: /* @__PURE__ */ jsx(TabsPrimitive2.Root, { ref, ...props, children }) })
926
+ );
927
+ Segment.List = forwardRef(
928
+ ({ className, ...props }, ref) => {
929
+ const { size } = useSegmentContext();
930
+ return /* @__PURE__ */ jsx(
931
+ TabsPrimitive2.List,
932
+ {
933
+ ref,
934
+ className: cn(segmentListVariants({ size }), className),
935
+ ...props
936
+ }
937
+ );
938
+ }
939
+ );
940
+ Segment.Item = forwardRef(
941
+ ({ className, leftIcon, children, ...props }, ref) => {
942
+ const { size } = useSegmentContext();
943
+ return /* @__PURE__ */ jsxs(
944
+ TabsPrimitive2.Trigger,
945
+ {
946
+ ref,
947
+ className: cn(segmentItemVariants({ size }), className),
948
+ ...props,
949
+ children: [
950
+ leftIcon && /* @__PURE__ */ jsx("span", { className: cn(segmentIconVariants({ size })), children: leftIcon }),
951
+ /* @__PURE__ */ jsx("span", { className: "flex items-center", children })
952
+ ]
953
+ }
954
+ );
955
+ }
956
+ );
957
+ Segment.Content = forwardRef(
958
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx(
959
+ TabsPrimitive2.Content,
960
+ {
961
+ ref,
962
+ className: cn(
963
+ "ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
964
+ className
965
+ ),
966
+ ...props
967
+ }
968
+ )
969
+ );
970
+ Segment.displayName = "Segment";
971
+ Segment.List.displayName = "Segment.List";
972
+ Segment.Content.displayName = "Segment.Content";
973
+ Segment.Item.displayName = "Segment.Item";
974
+ function FlatSegment({
975
+ items,
976
+ disabled,
977
+ className,
978
+ ...props
979
+ }) {
980
+ const rootProps = props;
981
+ return /* @__PURE__ */ jsx(Segment, { ...rootProps, children: /* @__PURE__ */ jsx(Segment.List, { className, children: items.map((item) => /* @__PURE__ */ createElement(Segment.Item, { ...item, key: item.value, disabled: disabled || item.disabled })) }) });
982
+ }
983
+ FlatSegment.displayName = "FlatSegment";
513
984
  var SelectContext = createContext(null);
514
985
  var useSelectContext = () => {
515
986
  const context = useContext(SelectContext);
@@ -982,4 +1453,4 @@ function ConditionalTooltip({ children, tooltip }) {
982
1453
  FlatTooltip.displayName = "FlatTooltip";
983
1454
  ConditionalTooltip.displayName = "ConditionalTooltip";
984
1455
 
985
- export { ColorPalette, ColorPaletteColors, ConditionalTooltip, DEFAULT_COLOR, FlatColorPalette, FlatSegment, FlatSelect, FlatTabs, FlatTooltip, ScrollArea, ScrollBar, Segment, Select, Tabs, Tooltip, colorPaletteColorClasses, commonInputVariants, getColorPaletteColor, isInPalette, overlayListVariants };
1456
+ export { ColorPalette, ColorPaletteColors, Combobox, ComboboxContent, ComboboxDescription, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxSearch, ComboboxTrigger, ComboboxValue, ConditionalTooltip, DEFAULT_COLOR, FlatColorPalette, FlatCombobox, FlatSegment, FlatSelect, FlatTabs, FlatTooltip, ScrollArea, ScrollBar, Segment, Select, Tabs, Tooltip, colorPaletteColorClasses, commonInputVariants, getColorPaletteColor, isInPalette, overlayListVariants, textFieldVariants };