@wipco/sdui 1.6.0 → 1.6.1

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 (85) hide show
  1. package/dist/{chunk-YZTTFEL4.js → chunk-34BABTH4.js} +1 -1
  2. package/dist/{chunk-7C54CKFZ.js → chunk-3PCR73OC.js} +2 -2
  3. package/dist/{chunk-KZ6U6FKB.js → chunk-3PT5OBOU.js} +1 -1
  4. package/dist/{chunk-NWYYNE3Q.js → chunk-4YPPL7JK.js} +1 -1
  5. package/dist/{chunk-M6H3SHIS.js → chunk-6YBSBC77.js} +1 -1
  6. package/dist/{chunk-QVS6K4FP.js → chunk-7G6J6QFC.js} +1 -1
  7. package/dist/{chunk-4OABUPIU.js → chunk-A57GKV5F.js} +2 -2
  8. package/dist/{chunk-AY4GM6KQ.js → chunk-AJ3KDBEE.js} +1 -1
  9. package/dist/{chunk-OYDJHQNZ.js → chunk-BV37UCDF.js} +2 -2
  10. package/dist/{chunk-WTIYILY3.js → chunk-CUFGH3LB.js} +1 -1
  11. package/dist/{chunk-V7BWMOHO.js → chunk-EGFDELSF.js} +1 -1
  12. package/dist/{chunk-HXLQSO66.js → chunk-ESAFQXEU.js} +2 -2
  13. package/dist/{chunk-RU5U2YMT.js → chunk-EUSC5NMZ.js} +3 -3
  14. package/dist/{chunk-X2NIRVLN.js → chunk-FP32LNFK.js} +1 -1
  15. package/dist/{chunk-6XI2VF2O.js → chunk-GKYUDTMI.js} +2 -2
  16. package/dist/{chunk-6TI4WF5Y.js → chunk-GSXD52XG.js} +2 -2
  17. package/dist/{chunk-CEVZAFPO.js → chunk-IIRVHSNK.js} +2 -2
  18. package/dist/{chunk-CSE3PZOZ.js → chunk-J7BZF4T4.js} +4 -4
  19. package/dist/{chunk-YNEEJCSZ.js → chunk-JHFA5RDN.js} +1 -1
  20. package/dist/{chunk-OUEJWC2Z.js → chunk-KDKRFWIF.js} +5 -5
  21. package/dist/{chunk-MN4RZ2WP.js → chunk-KO3EUNWB.js} +2 -2
  22. package/dist/{chunk-HRHKQOOF.js → chunk-NLSR3JYU.js} +1 -1
  23. package/dist/{chunk-53KS4E5N.js → chunk-O4EMQWCV.js} +9 -3
  24. package/dist/{chunk-VPOOIEKT.js → chunk-OCYJ2ZOV.js} +1 -1
  25. package/dist/{chunk-K6RE23XX.js → chunk-OKNF2SBB.js} +2 -2
  26. package/dist/{chunk-W4VA76QO.js → chunk-OQ7A3SFM.js} +1 -1
  27. package/dist/{chunk-YN7X7BEO.js → chunk-PCFH74RD.js} +3 -3
  28. package/dist/{chunk-WEG3V7ZB.js → chunk-SGGIWPP6.js} +2 -2
  29. package/dist/{chunk-XG22XKKD.js → chunk-TB7G5DXQ.js} +2 -2
  30. package/dist/{chunk-2KQL6DYG.js → chunk-TWUKNUUQ.js} +65 -9
  31. package/dist/{chunk-LIZTK3HO.js → chunk-UC725BGW.js} +1 -1
  32. package/dist/{chunk-NAIWQQPW.js → chunk-US3K6Q5T.js} +1 -1
  33. package/dist/{chunk-IQXLNICY.js → chunk-USNPJEXH.js} +4 -4
  34. package/dist/{chunk-AZSLSAJB.js → chunk-UZZLMPRW.js} +1 -1
  35. package/dist/{chunk-LKQJJSVJ.js → chunk-VAXRTBJH.js} +1 -1
  36. package/dist/{chunk-2QXA52DG.js → chunk-VQKX5PJ4.js} +3 -3
  37. package/dist/{chunk-CI5OZ2QT.js → chunk-VR5MFUD2.js} +1 -1
  38. package/dist/{chunk-FEKKOBPX.js → chunk-VSNHDHGS.js} +3 -3
  39. package/dist/{chunk-7JP52QQO.js → chunk-XFKNU6QN.js} +2 -2
  40. package/dist/{chunk-NA232CBX.js → chunk-XUVWIRZJ.js} +2 -2
  41. package/dist/{chunk-BLFJMMBW.js → chunk-YYAGE733.js} +17 -2
  42. package/dist/index.d.ts +35 -5
  43. package/dist/index.js +81 -33
  44. package/dist/meta.d.ts +1 -1
  45. package/dist/meta.js +116 -4
  46. package/dist/rich/ExcelUploadCard.js +3 -3
  47. package/dist/rich.d.ts +2 -1
  48. package/dist/rich.js +33 -6
  49. package/dist/styles.css +17 -0
  50. package/dist/{types-CYfIthux.d.ts → types-CMikpoN5.d.ts} +8 -1
  51. package/dist/widgets/ApprovalLineEditor.js +6 -6
  52. package/dist/widgets/ApprovalOverridesEditor.js +8 -8
  53. package/dist/widgets/ApprovalStepper.js +2 -2
  54. package/dist/widgets/AutocompleteField.js +6 -6
  55. package/dist/widgets/ColumnBoard.js +2 -2
  56. package/dist/widgets/DiffView.js +2 -2
  57. package/dist/widgets/Disclosure.js +2 -2
  58. package/dist/widgets/EventCalendar.js +2 -2
  59. package/dist/widgets/FileDropzone.js +5 -5
  60. package/dist/widgets/ImageLightbox.js +3 -3
  61. package/dist/widgets/InlineEdit.js +2 -2
  62. package/dist/widgets/JsonField.js +2 -2
  63. package/dist/widgets/OptionSchemaEditor.js +3 -3
  64. package/dist/widgets/OptionValueFields.js +3 -3
  65. package/dist/widgets/OrgChart.js +2 -2
  66. package/dist/widgets/OrgChartBoard.js +5 -5
  67. package/dist/widgets/PeriodFilter.js +3 -3
  68. package/dist/widgets/PermissionMatrixEditor.js +3 -3
  69. package/dist/widgets/PositionSelect.js +3 -3
  70. package/dist/widgets/PrintSheet.js +2 -2
  71. package/dist/widgets/ProfileEditDiffCard.js +3 -3
  72. package/dist/widgets/QRDisplay.js +3 -3
  73. package/dist/widgets/RankBoard.js +4 -4
  74. package/dist/widgets/RoleMemberPicker.js +4 -4
  75. package/dist/widgets/SearchableMultiPicker.js +4 -4
  76. package/dist/widgets/SecureScreen.js +2 -2
  77. package/dist/widgets/StagePeriodEditor.js +3 -3
  78. package/dist/widgets/TagInput.js +2 -2
  79. package/dist/widgets/TagMultiSelect.js +3 -3
  80. package/dist/widgets/Timeline.js +3 -3
  81. package/dist/widgets/TreePicker.js +5 -5
  82. package/dist/widgets/TreeView.d.ts +16 -2
  83. package/dist/widgets/TreeView.js +4 -4
  84. package/dist/widgets/index.js +70 -70
  85. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { CSSProperties, ReactNode, ComponentType } from 'react';
3
- import { S as SduiPage, a as SduiAction, b as SduiPropValue, c as SduiRule } from './types-CYfIthux.js';
4
- export { d as SduiArgRef, e as SduiCalcRef, f as SduiChild, g as SduiIndexRef, h as SduiItemRef, i as SduiNode, j as SduiPageQuery, k as SduiScalar, l as SduiStateRef } from './types-CYfIthux.js';
3
+ import { S as SduiPage, a as SduiAction, b as SduiPropValue, c as SduiRule } from './types-CMikpoN5.js';
4
+ export { d as SduiArgRef, e as SduiCalcRef, f as SduiChild, g as SduiIndexRef, h as SduiItemRef, i as SduiNode, j as SduiPageQuery, k as SduiScalar, l as SduiStateRef } from './types-CMikpoN5.js';
5
5
  import { S as SduiBoxProps, a as SduiContainerLayoutProps, b as SduiColumnsScale, c as SduiGapScale, d as SduiWeightScale, e as SduiTextAlignScale } from './layout-DmRikwZb.js';
6
6
  export { C as CHILD_LAYOUT_PROPS, L as LAYOUT_CSS, f as SduiAlignScale, g as SduiChildLayoutProps, h as SduiSizeScale, i as SduiSpanScale, j as childLayoutFrom, k as columnsClass, l as containerLayoutStyle, m as joinClass, n as mergeStyle, t as typographyStyle } from './layout-DmRikwZb.js';
7
7
  import { D as DatePickerProps, a as DateRangePickerProps, T as TimePickerProps } from './DatePicker-DX9juElE.js';
@@ -461,9 +461,14 @@ interface BadgeProps extends React__default.HTMLAttributes<HTMLSpanElement> {
461
461
  /** 선행 5px 점 — 라이브/진행 상태 */
462
462
  dot?: boolean;
463
463
  size?: 'md' | 'lg';
464
+ /**
465
+ * 긴 문구를 칸 폭 안에서 여러 줄로 감싼다(`wp-badge--wrap`, 1.6.1). 기본은 한 줄 고정 높이다.
466
+ * 예전에는 스펙이 style 로 height:auto·white-space:normal 등을 박아 흉내 냈다.
467
+ */
468
+ wrap?: boolean;
464
469
  children?: React__default.ReactNode;
465
470
  }
466
- declare function Badge({ tone, dot, size, children, className, ...rest }: BadgeProps): React__default.JSX.Element;
471
+ declare function Badge({ tone, dot, size, wrap, children, className, ...rest }: BadgeProps): React__default.JSX.Element;
467
472
  interface TagProps extends React__default.HTMLAttributes<HTMLSpanElement> {
468
473
  /** 선행 점의 CSS 색상 */
469
474
  color?: string;
@@ -793,7 +798,16 @@ interface ResultTableProps<T extends {
793
798
  };
794
799
  onSort?: (key: string) => void;
795
800
  onRowClick?: (row: T) => void;
801
+ /** 체크박스로 고른 행 — `aria-selected="true"`(선택 바탕)만 붙는다. SearchResults 의 일괄 선택이 여기로 온다. */
796
802
  selectedIds?: string[];
803
+ /**
804
+ * 표시 전용 강조 행(1.6.1) — `aria-current="true"` + `wp-row--selected` 클래스. 체크박스 선택과 별개다:
805
+ * 옆 창에 열어 둔 행처럼 "지금 보고 있는 것"을 가리킬 뿐, 일괄 액션의 대상이 되지 않는다.
806
+ * 그래서 체크 선택의 `aria-selected` 를 빌리지 않는다 — 같은 속성이면 스크린리더가 둘을 "선택됨"으로
807
+ * 똑같이 읽는다. 바탕·막대는 클래스가 칠한다(aria-selected 규칙에 기대지 않는다).
808
+ * SearchResults 의 `selectedIds` 가 이리로 온다. id 비교는 문자열로 한다(행 id 가 숫자인 JSON 도 맞게).
809
+ */
810
+ pickedIds?: readonly string[];
797
811
  /** rows가 비었을 때 표 대신 렌더 */
798
812
  empty?: React__default.ReactNode;
799
813
  /** true면 스크롤 창 안에서 보이는 행만 렌더한다 */
@@ -811,7 +825,7 @@ interface ResultTableProps<T extends {
811
825
  }
812
826
  declare function ResultTable<T extends {
813
827
  id: string;
814
- }>({ columns, rows, sort, onSort, onRowClick, selectedIds, empty, virtual, height, rowHeight, stackable, }: ResultTableProps<T>): React__default.JSX.Element;
828
+ }>({ columns, rows, sort, onSort, onRowClick, selectedIds, pickedIds, empty, virtual, height, rowHeight, stackable, }: ResultTableProps<T>): React__default.JSX.Element;
815
829
  interface ResultEmptyStateProps {
816
830
  /** 목록 이름 — 기본 문구에 들어간다("대여 이력이 없습니다") */
817
831
  title: string;
@@ -1277,6 +1291,17 @@ interface SearchResultsProps<T> {
1277
1291
  * (asset-18). endpoint 목록(RemoteSearchResults)은 이 값을 켠다.
1278
1292
  */
1279
1293
  serverFiltered?: boolean;
1294
+ /**
1295
+ * 표시 전용 강조(1.6.1) — 이 id 의 행(목록 보기)·카드(카드 보기)를 강조한다. 체크박스 선택(`actions`)과
1296
+ * **별개**다: 일괄 액션의 대상이 되지 않고, 선택 바도 세우지 않는다. 옆 창·상세에 열어 둔 행을 목록에서
1297
+ * 가리키는 자리다 — 스펙은 `"selectedIds": [{"$state":"rt.$picked.id"}]` 처럼 준다.
1298
+ *
1299
+ * 행은 `aria-current="true"` + `wp-row--selected`, 카드는 `wp-card--selected` + `is-selected` +
1300
+ * `aria-current="true"` 다. 체크 선택의 `aria-selected` 는 쓰지 않는다 — 스크린리더가 강조와 체크 선택을
1301
+ * 똑같이 "선택됨"으로 읽게 되고, 카드(버튼·일반 상자 역할)는 aria-selected 를 가질 수도 없다. 비교는
1302
+ * 문자열로 하고, 바인딩이 아직 비어 `null`·`undefined` 인 원소는 버린다.
1303
+ */
1304
+ selectedIds?: string[];
1280
1305
  }
1281
1306
  /**
1282
1307
  * 스펙이 준 페이지 크기 목록을 다듬는다 — 양의 정수만, 중복 제거, 오름차순.
@@ -1285,7 +1310,7 @@ interface SearchResultsProps<T> {
1285
1310
  declare function normalizePageSizes(sizes: number[] | undefined): number[] | undefined;
1286
1311
  declare function SearchResults<T extends {
1287
1312
  id: string;
1288
- }>({ item, columns, gridConfig, leftFilters, rightFilters, tabs, summary, initialView, views, pageSizes, className, style, searchParams, onParamsChange, actions, disableGrid, disableList, onRowClick, title, headerActions, isLoading, hideHeader, advancedSearchFields: rawAdvancedSearchFields, searchPlaceholder, virtual, serverUnsortable, primaryKey, emptyTitle, emptyText, serverFiltered, }: SearchResultsProps<T>): React__default.JSX.Element;
1313
+ }>({ item, columns, gridConfig, leftFilters, rightFilters, tabs, summary, initialView, views, pageSizes, className, style, searchParams, onParamsChange, actions, disableGrid, disableList, onRowClick, title, headerActions, isLoading, hideHeader, advancedSearchFields: rawAdvancedSearchFields, searchPlaceholder, virtual, serverUnsortable, primaryKey, emptyTitle, emptyText, serverFiltered, selectedIds, }: SearchResultsProps<T>): React__default.JSX.Element;
1289
1314
 
1290
1315
  /**
1291
1316
  * 셀 표현 어휘 — 목록 컬럼의 셀과 카드 행의 값이 **같은 규칙**을 쓴다.
@@ -1577,6 +1602,11 @@ interface SduiSearchCommonProps {
1577
1602
  * 조건이 없으면 빈 문자열. 생략하면 아무것도 적지 않는다.
1578
1603
  */
1579
1604
  queryStateKey?: string;
1605
+ /**
1606
+ * 표시 전용 강조 — 이 id 의 행·카드를 강조한다(체크박스 선택과 별개, 일괄 액션 대상 아님).
1607
+ * 옆 창에 열어 둔 행을 가리키는 자리: `"selectedIds": [{"$state":"rt.$picked.id"}]`. 계약은 SearchResultsProps.selectedIds.
1608
+ */
1609
+ selectedIds?: string[];
1580
1610
  }
1581
1611
  interface SduiSearchResultsProps extends SduiSearchCommonProps {
1582
1612
  data: SearchRow[];
package/dist/index.js CHANGED
@@ -1,23 +1,23 @@
1
- export { loadOptionalModule } from './chunk-NWYYNE3Q.js';
2
- import { useSduiDispatch, SduiDialog, useSduiCan, useSduiRuntime, SduiDirtyRegistryContext, SduiLeaveRegistryContext, SduiFormScopeContext, SduiDispatchContext, SduiRuntimeContext, SduiPermissionProvider } from './chunk-CI5OZ2QT.js';
3
- export { SduiDialog, SduiPermissionProvider, useSduiCan, useSduiDispatch, useSduiRuntime } from './chunk-CI5OZ2QT.js';
4
- import { Text, Spacer, Show, Section, Row, PageHead, KeyValueList, Grid, Divider, Col, Actions } from './chunk-LIZTK3HO.js';
5
- export { Actions, Col, Divider, Grid, KeyValueList, PageHead, Row, Section, Show, Spacer, Text } from './chunk-LIZTK3HO.js';
6
- import { ImageViewer } from './chunk-AZSLSAJB.js';
7
- export { ImageViewer } from './chunk-AZSLSAJB.js';
8
- import { normalizeSearchFields, searchValuesFromParams, splitMultiValue, includesLooseSearch, cascadingValuePaths, SearchToolbar, searchFieldKeys, Popover } from './chunk-4OABUPIU.js';
9
- export { SearchToolbar, cascadingValuePaths, cleanSearchValues, includesLooseSearch, joinMultiValue, normalizeSearchText, searchFieldKeys, searchValuesFromParams, splitMultiValue } from './chunk-4OABUPIU.js';
10
- import { parseYmd, YMD_RE, TimePicker, DateRangePicker, DatePicker } from './chunk-X2NIRVLN.js';
11
- export { DatePicker, DateRangePicker, TimePicker } from './chunk-X2NIRVLN.js';
1
+ export { loadOptionalModule } from './chunk-4YPPL7JK.js';
2
+ import { useSduiDispatch, SduiDialog, useSduiCan, useSduiRuntime, SduiDirtyRegistryContext, SduiLeaveRegistryContext, SduiFormScopeContext, SduiDispatchContext, SduiRuntimeContext, SduiPermissionProvider } from './chunk-VR5MFUD2.js';
3
+ export { SduiDialog, SduiPermissionProvider, useSduiCan, useSduiDispatch, useSduiRuntime } from './chunk-VR5MFUD2.js';
4
+ import { Text, Spacer, Show, Section, Row, PageHead, KeyValueList, Grid, Divider, Col, Actions } from './chunk-UC725BGW.js';
5
+ export { Actions, Col, Divider, Grid, KeyValueList, PageHead, Row, Section, Show, Spacer, Text } from './chunk-UC725BGW.js';
6
+ import { ImageViewer } from './chunk-UZZLMPRW.js';
7
+ export { ImageViewer } from './chunk-UZZLMPRW.js';
8
+ import { normalizeSearchFields, searchValuesFromParams, splitMultiValue, includesLooseSearch, cascadingValuePaths, SearchToolbar, searchFieldKeys, Popover } from './chunk-A57GKV5F.js';
9
+ export { SearchToolbar, cascadingValuePaths, cleanSearchValues, includesLooseSearch, joinMultiValue, normalizeSearchText, searchFieldKeys, searchValuesFromParams, splitMultiValue } from './chunk-A57GKV5F.js';
10
+ import { parseYmd, YMD_RE, TimePicker, DateRangePicker, DatePicker } from './chunk-FP32LNFK.js';
11
+ export { DatePicker, DateRangePicker, TimePicker } from './chunk-FP32LNFK.js';
12
12
  import { OverlayContainerContext, OverlayLayer, useAnyModalOpen } from './chunk-BITS7UJY.js';
13
13
  export { OverlayContainerContext, OverlayLayer, getOverlayRoot, useAnyModalOpen, useOverlayLayer } from './chunk-BITS7UJY.js';
14
14
  import { HoistedStyle } from './chunk-RIZRM7OO.js';
15
- import { useSduiAdapter, hostFetchOf, isSafeNavigationTarget, useSduiSandbox, resolveAdapter, assetResolverOf, SduiAdapterContext } from './chunk-YNEEJCSZ.js';
16
- export { defaultAdapter, useSduiAssetResolver, useSduiSandbox } from './chunk-YNEEJCSZ.js';
15
+ import { useSduiAdapter, hostFetchOf, isSafeNavigationTarget, useSduiSandbox, resolveAdapter, assetResolverOf, SduiAdapterContext } from './chunk-JHFA5RDN.js';
16
+ export { defaultAdapter, useSduiAssetResolver, useSduiSandbox } from './chunk-JHFA5RDN.js';
17
17
  import { DEV, useIsMobile } from './chunk-GSM664TX.js';
18
18
  export { MOBILE_MEDIA_QUERY, useIsMobile } from './chunk-GSM664TX.js';
19
- import { EmptyState, Button, Checkbox, Select, Tabs, SegmentedControl, Spinner, Pagination, fieldOf, StatCard, isZonedIsoDateTime, formatDateValue, Icon, Card, Badge, ProgressBar, Tag, Toast, Textarea, Table, Switch, Input, IconButton, Field, Alert, warnOnce, isPlainObject, CALC_OPS, evaluateCalc, Dialog, ICON_NODES, toNumber } from './chunk-BLFJMMBW.js';
20
- export { Alert, Avatar, Badge, Breadcrumb, Button, CALC_OPS, Card, Checkbox, Dialog, EmptyState, Field, Icon, IconButton, Input, Pagination, ProgressBar, Radio, SegmentedControl, Select, SidebarNav, Spinner, StatCard, Switch, Table, Tabs, Tag, Textarea, Toast, Tooltip, formatDateValue, formatDisplayValue, formatNumberValue, isZonedIsoDateTime, parseNumeric } from './chunk-BLFJMMBW.js';
19
+ import { EmptyState, Button, Checkbox, Select, Tabs, SegmentedControl, Spinner, Pagination, fieldOf, StatCard, isZonedIsoDateTime, formatDateValue, Icon, Card, Badge, ProgressBar, Tag, Toast, Textarea, Table, Switch, Input, IconButton, Field, Alert, warnOnce, isPlainObject, CALC_OPS, evaluateCalc, Dialog, ICON_NODES, toNumber } from './chunk-YYAGE733.js';
20
+ export { Alert, Avatar, Badge, Breadcrumb, Button, CALC_OPS, Card, Checkbox, Dialog, EmptyState, Field, Icon, IconButton, Input, Pagination, ProgressBar, Radio, SegmentedControl, Select, SidebarNav, Spinner, StatCard, Switch, Table, Tabs, Tag, Textarea, Toast, Tooltip, formatDateValue, formatDisplayValue, formatNumberValue, isZonedIsoDateTime, parseNumeric } from './chunk-YYAGE733.js';
21
21
  import { boxed, LAYOUT_CSS, childLayoutFrom, CHILD_LAYOUT_PROPS } from './chunk-3JTBOABA.js';
22
22
  export { CHILD_LAYOUT_PROPS, LAYOUT_CSS, boxed, childLayoutFrom, columnsClass, containerLayoutStyle, joinClass, mergeStyle, typographyStyle } from './chunk-3JTBOABA.js';
23
23
  import React9, { createContext, useState, useMemo, useEffect, useRef, useContext, useCallback, useSyncExternalStore } from 'react';
@@ -747,6 +747,7 @@ function ResultTable({
747
747
  onSort,
748
748
  onRowClick,
749
749
  selectedIds,
750
+ pickedIds,
750
751
  empty,
751
752
  virtual = false,
752
753
  height = 560,
@@ -767,6 +768,7 @@ function ResultTable({
767
768
  });
768
769
  if (!rows.length && empty) return /* @__PURE__ */ jsx(Fragment, { children: empty });
769
770
  const selectedSet = selectedIds && selectedIds.length > 0 ? new Set(selectedIds) : null;
771
+ const pickedSet = pickedIds && pickedIds.length > 0 ? new Set(pickedIds) : null;
770
772
  const unit = measured ?? rowHeight;
771
773
  const start = virtual ? Math.max(0, Math.floor(scrollTop / unit) - OVERSCAN) : 0;
772
774
  const end = virtual ? Math.min(rows.length, Math.ceil((scrollTop + height) / unit) + OVERSCAN) : rows.length;
@@ -804,11 +806,14 @@ function ResultTable({
804
806
  rows.slice(start, end).map((row, offset) => {
805
807
  const index = start + offset;
806
808
  const selected = selectedSet ? selectedSet.has(row.id) : false;
809
+ const picked = pickedSet ? pickedSet.has(String(row.id)) : false;
807
810
  return /* @__PURE__ */ jsx(
808
811
  "tr",
809
812
  {
810
813
  ref: offset === 0 ? firstRowRef : void 0,
811
814
  "aria-selected": selected || void 0,
815
+ "aria-current": picked ? "true" : void 0,
816
+ className: picked ? "wp-row--selected" : void 0,
812
817
  onClick: onRowClick ? () => onRowClick(row) : void 0,
813
818
  style: onRowClick ? { cursor: "pointer" } : void 0,
814
819
  children: columns.map((column) => {
@@ -868,6 +873,15 @@ function ResultEmptyState({ title, filtered = false, emptyTitle, emptyText, scop
868
873
  }
869
874
  return /* @__PURE__ */ jsx(EmptyState, { title: emptyTitle || `${scoped ? "" : "\uC544\uC9C1 "}${name}${josaOf(name, "\uC774/\uAC00")} \uC5C6\uC2B5\uB2C8\uB2E4`, tight: true, children: emptyText || void 0 });
870
875
  }
876
+ function normalizeSelectedIds(ids) {
877
+ if (!Array.isArray(ids)) return [];
878
+ const out = [];
879
+ for (const id of ids) {
880
+ if (typeof id === "string" && id !== "") out.push(id);
881
+ else if (typeof id === "number" && Number.isFinite(id)) out.push(String(id));
882
+ }
883
+ return out;
884
+ }
871
885
  var EMPTY_FILTERS = [];
872
886
  var EMPTY_FIELDS = [];
873
887
  var PAGE_SIZE_CHOICES = [10, 20, 50, 100];
@@ -951,10 +965,13 @@ function SearchResults({
951
965
  primaryKey,
952
966
  emptyTitle,
953
967
  emptyText,
954
- serverFiltered = false
968
+ serverFiltered = false,
969
+ selectedIds
955
970
  }) {
956
971
  const hasActions = actions.length > 0;
957
972
  const isMobile = useIsMobile();
973
+ const pickedIds = normalizeSelectedIds(selectedIds);
974
+ const pickedSet = pickedIds.length > 0 ? new Set(pickedIds) : null;
958
975
  const advancedSearchFields = useMemo(
959
976
  () => normalizeSearchFields(rawAdvancedSearchFields),
960
977
  [rawAdvancedSearchFields]
@@ -1364,10 +1381,20 @@ function SearchResults({
1364
1381
  onSort: handleSort,
1365
1382
  onRowClick,
1366
1383
  selectedIds: hasActions ? Array.from(selected) : void 0,
1384
+ pickedIds: pickedSet ? pickedIds : void 0,
1367
1385
  empty,
1368
1386
  virtual: virtualListActive
1369
1387
  }
1370
- ) : visibleItems.length === 0 ? empty : /* @__PURE__ */ jsx("div", { className: "wp-grid wp-grid--3", children: visibleItems.map((row) => /* @__PURE__ */ jsx(GridCard, { item: row, config: gridConfig, onClick: onRowClick }, row.id)) }),
1388
+ ) : visibleItems.length === 0 ? empty : /* @__PURE__ */ jsx("div", { className: "wp-grid wp-grid--3", children: visibleItems.map((row) => /* @__PURE__ */ jsx(
1389
+ GridCard,
1390
+ {
1391
+ item: row,
1392
+ config: gridConfig,
1393
+ onClick: onRowClick,
1394
+ picked: pickedSet ? pickedSet.has(String(row.id)) : false
1395
+ },
1396
+ row.id
1397
+ )) }),
1371
1398
  virtualListActive && clientPaginated || totalCount === 0 && !isLoading ? null : /* @__PURE__ */ jsxs("div", { className: "wp-row wp-row--between", children: [
1372
1399
  /* @__PURE__ */ jsxs("div", { className: "wp-row", style: { flex: "none" }, children: [
1373
1400
  /* @__PURE__ */ jsx("span", { className: "wp-caption", style: { whiteSpace: "nowrap" }, children: "\uD398\uC774\uC9C0\uB2F9" }),
@@ -1419,7 +1446,8 @@ function resolveRowPart(part, item) {
1419
1446
  function GridCard({
1420
1447
  item,
1421
1448
  config,
1422
- onClick
1449
+ onClick,
1450
+ picked = false
1423
1451
  }) {
1424
1452
  if (!config) return null;
1425
1453
  const badge = config.badge?.(item) ?? null;
@@ -1436,6 +1464,7 @@ function GridCard({
1436
1464
  Card,
1437
1465
  {
1438
1466
  interactive: Boolean(onClick),
1467
+ ...picked ? { selected: true, className: "is-selected", "aria-current": "true" } : {},
1439
1468
  cover: config.cover?.(item),
1440
1469
  title: config.title(item),
1441
1470
  subtitle: config.subtitle?.(item),
@@ -1627,7 +1656,8 @@ function SduiSearchResultsImpl({
1627
1656
  virtual,
1628
1657
  emptyTitle,
1629
1658
  emptyText,
1630
- queryStateKey
1659
+ queryStateKey,
1660
+ selectedIds
1631
1661
  }) {
1632
1662
  const dispatch = useSduiDispatch();
1633
1663
  const [params, setParams] = useState(() => new URLSearchParams());
@@ -1656,6 +1686,7 @@ function SduiSearchResultsImpl({
1656
1686
  primaryKey: gridCard?.titleKey,
1657
1687
  emptyTitle,
1658
1688
  emptyText,
1689
+ selectedIds,
1659
1690
  onRowClick: rowClick ? (row) => toList(rowClick).forEach((a) => dispatch(a, row)) : void 0,
1660
1691
  searchParams: params,
1661
1692
  onParamsChange: setParams
@@ -1687,7 +1718,8 @@ function RemoteSearchResultsImpl({
1687
1718
  summary,
1688
1719
  emptyTitle,
1689
1720
  emptyText,
1690
- queryStateKey
1721
+ queryStateKey,
1722
+ selectedIds
1691
1723
  }) {
1692
1724
  const dispatch = useSduiDispatch();
1693
1725
  const defaultPageSize = normalizePageSizes(pageSizes)?.[0] ?? 10;
@@ -1760,6 +1792,7 @@ function RemoteSearchResultsImpl({
1760
1792
  primaryKey: gridCard?.titleKey,
1761
1793
  emptyTitle,
1762
1794
  emptyText,
1795
+ selectedIds,
1763
1796
  summary: summary ? /* @__PURE__ */ jsx(SearchSummaryCards, { items: summary.items, values: summaryState.values, dispatch }) : void 0,
1764
1797
  onRowClick: rowClick ? (row) => toList(rowClick).forEach((a) => dispatch(a, row)) : void 0,
1765
1798
  searchParams: params,
@@ -3333,6 +3366,24 @@ function urlSeedSettled(state, seeded, baseline) {
3333
3366
  (key) => Object.is(state[key], seeded[key]) || !Object.is(state[key], baseline[key])
3334
3367
  );
3335
3368
  }
3369
+ function encodeUrlStateValue(value) {
3370
+ if (value === void 0 || value === null || value === "") return null;
3371
+ if (typeof value !== "string") return JSON.stringify(value);
3372
+ if (/^["[{]/.test(value)) return JSON.stringify(value);
3373
+ try {
3374
+ JSON.parse(value);
3375
+ return JSON.stringify(value);
3376
+ } catch {
3377
+ return value;
3378
+ }
3379
+ }
3380
+ function decodeUrlStateValue(raw) {
3381
+ try {
3382
+ return JSON.parse(raw);
3383
+ } catch {
3384
+ return raw;
3385
+ }
3386
+ }
3336
3387
  function SduiRenderer({
3337
3388
  page,
3338
3389
  registry = defaultRegistry,
@@ -3397,13 +3448,7 @@ function SduiRenderer({
3397
3448
  const seeded = {};
3398
3449
  for (const key of page.urlState) {
3399
3450
  const raw = params.get(key);
3400
- if (raw !== null) {
3401
- try {
3402
- seeded[key] = JSON.parse(raw);
3403
- } catch {
3404
- seeded[key] = raw;
3405
- }
3406
- }
3451
+ if (raw !== null) seeded[key] = decodeUrlStateValue(raw);
3407
3452
  }
3408
3453
  if (Object.keys(seeded).length > 0) {
3409
3454
  const baseline = {};
@@ -3433,16 +3478,19 @@ function SduiRenderer({
3433
3478
  const params = new URLSearchParams(window.location.search);
3434
3479
  let changed = false;
3435
3480
  for (const key of page.urlState) {
3436
- const value = state[key];
3437
- const serialized = value === void 0 || value === null || value === "" ? null : JSON.stringify(value);
3481
+ const serialized = encodeUrlStateValue(state[key]);
3482
+ const current = params.get(key);
3438
3483
  if (serialized === null) {
3439
- if (params.has(key)) {
3484
+ if (current !== null) {
3440
3485
  params.delete(key);
3441
3486
  changed = true;
3442
3487
  }
3443
- } else if (params.get(key) !== serialized) {
3444
- params.set(key, serialized);
3445
- changed = true;
3488
+ } else {
3489
+ const sameValue = current !== null && (current === serialized || encodeUrlStateValue(decodeUrlStateValue(current)) === serialized);
3490
+ if (!sameValue) {
3491
+ params.set(key, serialized);
3492
+ changed = true;
3493
+ }
3446
3494
  }
3447
3495
  }
3448
3496
  if (changed) {
package/dist/meta.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { b as SduiPropValue, i as SduiNode } from './types-CYfIthux.js';
1
+ import { b as SduiPropValue, i as SduiNode } from './types-CMikpoN5.js';
2
2
 
3
3
  /**
4
4
  * 시각 빌더용 컴포넌트 메타데이터 스키마.
package/dist/meta.js CHANGED
@@ -947,6 +947,39 @@ var ButtonMeta = {
947
947
  group: "behavior",
948
948
  advanced: true
949
949
  },
950
+ {
951
+ name: "aria-label",
952
+ kind: "string",
953
+ label: "\uC811\uADFC\uC131 \uB77C\uBCA8",
954
+ bindable: true,
955
+ description: "\uBCF4\uC774\uB294 \uAE00\uC790 \uC5C6\uC774 \uC544\uC774\uCF58\uB9CC \uC788\uB294 \uBC84\uD2BC \uB4F1 \u2014 \uC2A4\uD06C\uB9B0\uB9AC\uB354\uAC00 \uC77D\uC744 \uC774\uB984. \uD589\uB9C8\uB2E4 \uB2E4\uB974\uBA74 $calc/$item \uC73C\uB85C \uC5EE\uB294\uB2E4.",
956
+ group: "content",
957
+ advanced: true
958
+ },
959
+ {
960
+ name: "role",
961
+ kind: "enum",
962
+ label: "\uC811\uADFC\uC131 \uC5ED\uD560",
963
+ description: '\uBCF4\uC870\uAE30\uC220\uC5D0 \uBC84\uD2BC\uC744 \uB2E4\uB978 \uC5ED\uD560\uB85C \uC54C\uB9B0\uB2E4(\uB098\uBA38\uC9C0 \uD504\uB86D\uCC98\uB7FC <button>\uC5D0 \uADF8\uB300\uB85C \uC5B9\uD78C\uB2E4). \uB2E8\uC77C \uC120\uD0DD \uBB36\uC74C(Row/Col role="radiogroup") \uC548\uC758 \uC120\uD0DD\uC9C0 \uBC84\uD2BC\uC774 radio \uB2E4 \u2014 \uADF8\uB54C aria-checked \uB97C \uAC19\uC774 \uC900\uB2E4.',
964
+ options: [
965
+ { value: "radio", label: "\uB2E8\uC77C \uC120\uD0DD \uD56D\uBAA9(radio)" },
966
+ { value: "checkbox", label: "\uCF1C\uACE0 \uB044\uB294 \uD56D\uBAA9(checkbox)" },
967
+ { value: "switch", label: "\uC2A4\uC704\uCE58(switch)" },
968
+ { value: "tab", label: "\uD0ED(tab)" },
969
+ { value: "menuitem", label: "\uBA54\uB274 \uD56D\uBAA9(menuitem)" }
970
+ ],
971
+ group: "behavior",
972
+ advanced: true
973
+ },
974
+ {
975
+ name: "aria-checked",
976
+ kind: "boolean",
977
+ label: "\uC811\uADFC\uC131: \uC120\uD0DD\uB428",
978
+ bindable: true,
979
+ description: 'role \uC774 radio\xB7checkbox\xB7switch \uC77C \uB54C \uC774 \uBC84\uD2BC\uC774 \uACE8\uB77C\uC838 \uC788\uB294\uAC00. \uBCF4\uD1B5 \uC0C1\uD0DC\uC640 \uBE44\uAD50\uD574 \uC5EE\uB294\uB2E4 \u2014 {"$calc":{"op":"eq","args":[{"$item":"key"},{"$state":"filter"}]}}. \uBAA8\uC591\uC740 \uBC14\uAFB8\uC9C0 \uC54A\uC73C\uB2C8 variant \uB3C4 \uAC19\uC774 \uC5EE\uB294\uB2E4.',
980
+ group: "behavior",
981
+ advanced: true
982
+ },
950
983
  { name: "onClick", kind: "action", label: "\uD074\uB9AD", group: "behavior" },
951
984
  styleProp,
952
985
  classNameProp,
@@ -992,6 +1025,15 @@ var CheckboxMeta = {
992
1025
  group: "data"
993
1026
  },
994
1027
  { name: "disabled", kind: "boolean", label: "\uBE44\uD65C\uC131", default: false, bindable: true, group: "behavior" },
1028
+ {
1029
+ name: "aria-label",
1030
+ kind: "string",
1031
+ label: "\uC811\uADFC\uC131 \uB77C\uBCA8",
1032
+ bindable: true,
1033
+ description: "\uBCF4\uC774\uB294 \uB77C\uBCA8 \uC5C6\uC774 \uC0C1\uC790\uB9CC \uB458 \uB54C(\uD45C \uCE78\xB7\uBC18\uBCF5 \uD589) \uC2A4\uD06C\uB9B0\uB9AC\uB354\uAC00 \uC77D\uC744 \uC774\uB984 \u2014 \uC228\uC740 <input>\uC5D0 \uBD99\uB294\uB2E4. \uD589\uB9C8\uB2E4 \uB2E4\uB974\uBA74 $calc/$item \uC73C\uB85C \uC5EE\uB294\uB2E4.",
1034
+ group: "content",
1035
+ advanced: true
1036
+ },
995
1037
  classNameProp
996
1038
  ],
997
1039
  children: { accepts: false },
@@ -1348,6 +1390,15 @@ var IconButtonMeta = {
1348
1390
  },
1349
1391
  { name: "onClick", kind: "action", label: "\uD074\uB9AD", group: "behavior" },
1350
1392
  { name: "disabled", kind: "boolean", label: "\uBE44\uD65C\uC131", default: false, bindable: true, group: "behavior" },
1393
+ {
1394
+ name: "aria-label",
1395
+ kind: "string",
1396
+ label: "\uC811\uADFC\uC131 \uB77C\uBCA8(\uB9CC)",
1397
+ bindable: true,
1398
+ description: "\uD234\uD301(title) \uC5C6\uC774 \uC2A4\uD06C\uB9B0\uB9AC\uB354 \uC774\uB984\uB9CC \uC904 \uB54C. \uBCF4\uD1B5\uC740 label \uD558\uB098\uBA74 \uB41C\uB2E4(aria-label\xB7title \uB458 \uB2E4 \uB41C\uB2E4). \uB458 \uB2E4 \uC8FC\uBA74 aria-label \uC740 \uC774\uCABD\uC774 \uC774\uAE34\uB2E4.",
1399
+ group: "content",
1400
+ advanced: true
1401
+ },
1351
1402
  styleProp,
1352
1403
  classNameProp
1353
1404
  ],
@@ -1414,6 +1465,15 @@ var InputMeta = {
1414
1465
  { name: "max", kind: "number", label: "\uCD5C\uB300\uAC12", description: "type=number/date\uC758 \uC0C1\uD55C", group: "validation" },
1415
1466
  { name: "step", kind: "number", label: "\uC99D\uAC10 \uB2E8\uC704", group: "validation", advanced: true },
1416
1467
  { name: "title", kind: "string", label: "\uD234\uD301", group: "content", advanced: true },
1468
+ {
1469
+ name: "aria-label",
1470
+ kind: "string",
1471
+ label: "\uC811\uADFC\uC131 \uB77C\uBCA8",
1472
+ bindable: true,
1473
+ description: "Field \uB77C\uBCA8\uC774 \uC5C6\uC744 \uB54C(\uD45C \uCE78\xB7\uBC18\uBCF5 \uD589\uC758 \uC785\uB825) \uC2A4\uD06C\uB9B0\uB9AC\uB354\uAC00 \uC77D\uC744 \uC774\uB984. \uD589\uB9C8\uB2E4 \uB2E4\uB974\uBA74 $calc/$item \uC73C\uB85C \uC5EE\uB294\uB2E4.",
1474
+ group: "content",
1475
+ advanced: true
1476
+ },
1417
1477
  {
1418
1478
  name: "trailing",
1419
1479
  kind: "icon",
@@ -1541,6 +1601,15 @@ var SwitchMeta = {
1541
1601
  group: "appearance"
1542
1602
  },
1543
1603
  { name: "disabled", kind: "boolean", label: "\uBE44\uD65C\uC131", default: false, bindable: true, group: "behavior" },
1604
+ {
1605
+ name: "aria-label",
1606
+ kind: "string",
1607
+ label: "\uC811\uADFC\uC131 \uB77C\uBCA8",
1608
+ bindable: true,
1609
+ description: '\uBCF4\uC774\uB294 \uB77C\uBCA8 \uC5C6\uC774 \uD1A0\uAE00\uB9CC \uB458 \uB54C \uC2A4\uD06C\uB9B0\uB9AC\uB354\uAC00 \uC77D\uC744 \uC774\uB984 \u2014 \uC228\uC740 <input role="switch">\uC5D0 \uBD99\uB294\uB2E4.',
1610
+ group: "content",
1611
+ advanced: true
1612
+ },
1544
1613
  classNameProp
1545
1614
  ],
1546
1615
  children: { accepts: false },
@@ -1619,6 +1688,14 @@ var BadgeMeta = {
1619
1688
  ],
1620
1689
  group: "appearance"
1621
1690
  },
1691
+ {
1692
+ name: "wrap",
1693
+ kind: "boolean",
1694
+ label: "\uC904\uBC14\uAFC8",
1695
+ default: false,
1696
+ description: "\uAE34 \uBB38\uAD6C\uB97C \uD55C \uC904\uB85C \uB450\uC9C0 \uC54A\uACE0 \uCE78 \uD3ED \uC548\uC5D0\uC11C \uC5EC\uB7EC \uC904\uB85C \uAC10\uC2FC\uB2E4(\uB192\uC774\uB294 \uAE00\uC5D0 \uB9DE\uCDB0 \uB298\uC5B4\uB09C\uB2E4).",
1697
+ group: "appearance"
1698
+ },
1622
1699
  classNameProp
1623
1700
  ],
1624
1701
  children: { accepts: true, text: true, label: "\uBC30\uC9C0 \uBB38\uAD6C" },
@@ -2425,6 +2502,14 @@ var searchCommonProps = [
2425
2502
  advanced: true
2426
2503
  },
2427
2504
  { name: "rowClick", kind: "action", label: "\uD589 \uD074\uB9AD", eventArg: "\uD589 \uAC1D\uCCB4 \uC804\uCCB4", group: "behavior" },
2505
+ {
2506
+ name: "selectedIds",
2507
+ kind: "binding",
2508
+ label: "\uAC15\uC870\uD560 \uD589 id",
2509
+ bindable: true,
2510
+ description: '\uC774 id \uB4E4\uC758 \uD589(\uBAA9\uB85D)\xB7\uCE74\uB4DC(\uCE74\uB4DC \uBCF4\uAE30)\uB97C \uAC15\uC870\uD55C\uB2E4 \u2014 \uD45C\uC2DC \uC804\uC6A9\uC774\uB77C \uCCB4\uD06C\uBC15\uC2A4 \uC120\uD0DD\xB7\uC77C\uAD04 \uC561\uC158\uACFC \uBB34\uAD00\uD558\uB2E4. \uC606 \uCC3D\uC5D0 \uC5F4\uC5B4 \uB454 \uD589\uC744 \uAC00\uB9AC\uD0AC \uB54C [{"$state":"rt.$picked.id"}]\uCC98\uB7FC \uC900\uB2E4. \uBE44\uC5B4 \uC788\uAC70\uB098 null \uC778 \uC6D0\uC18C\uB294 \uBB34\uC2DC\uD55C\uB2E4.',
2511
+ group: "data"
2512
+ },
2428
2513
  {
2429
2514
  name: "virtual",
2430
2515
  kind: "boolean",
@@ -2432,7 +2517,9 @@ var searchCommonProps = [
2432
2517
  description: "true\uBA74 150\uD589\uBD80\uD130. \uC22B\uC790\uB97C \uC8FC\uBA74 \uADF8 \uAC12\uC774 \uC784\uACC4 \uD589\uC218\uAC00 \uB41C\uB2E4.",
2433
2518
  group: "behavior",
2434
2519
  advanced: true
2435
- }
2520
+ },
2521
+ // 뿌리 상자(boxed)에 붙는다 — 소비 앱 시트의 옵트인 훅 자리(예: 태블릿에서 data-mobile=hide 열 숨기기).
2522
+ classNameProp
2436
2523
  ];
2437
2524
  var searchSlots = [
2438
2525
  {
@@ -3523,7 +3610,7 @@ var ChartMeta = {
3523
3610
  kind: "boolean",
3524
3611
  label: "x\uCD95 \uB77C\uBCA8 \uBAA8\uB450 \uBCF4\uC774\uAE30",
3525
3612
  default: false,
3526
- description: "\uB9C9\uB300/\uC120 \uCC28\uD2B8 \uC804\uC6A9. \uAE34 \uBC94\uC8FC \uB77C\uBCA8(\uBCF8\uBD80\uBA85 \uB4F1)\uC744 \uCE78 \uD3ED\uC5D0 \uB9DE\uCDB0 \uCD5C\uB300 3\uC904\uB85C \uC904\uBC14\uAFC8\uD558\uACE0, \uADF8\uB798\uB3C4 \uBAA8\uC790\uB77C\uBA74 45\xB0 \uAE30\uC6B8\uC5EC \uC804\uBD80 \uBCF4\uC778\uB2E4. \uB044\uBA74 \uACB9\uCE58\uB294 \uB77C\uBCA8\uC744 \uAC74\uB108\uB6F4\uB2E4.",
3613
+ description: "\uB9C9\uB300/\uC120 \uCC28\uD2B8 \uC804\uC6A9. \uAE34 \uBC94\uC8FC \uB77C\uBCA8(\uBCF8\uBD80\uBA85 \uB4F1)\uC744 \uCE78 \uD3ED\uC5D0 \uB9DE\uCDB0 \uCD5C\uB300 3\uC904\uB85C \uC904\uBC14\uAFC8\uD558\uACE0, \uADF8\uB798\uB3C4 \uBAA8\uC790\uB77C\uBA74 45\xB0 \uAE30\uC6B8\uC5EC \uC804\uBD80 \uBCF4\uC778\uB2E4(\uAE30\uC6B8\uC774\uBA74 \uCCAB \uB77C\uBCA8\uC774 \uC798\uB9AC\uC9C0 \uC54A\uAC8C \uC67C\uCABD \uC5EC\uBC31\uC744 \uB77C\uBCA8 \uAE38\uC774\uB9CC\uD07C \uB298\uB9B0\uB2E4). \uB044\uBA74 \uACB9\uCE58\uB294 \uB77C\uBCA8\uC744 \uAC74\uB108\uB6F4\uB2E4.",
3527
3614
  group: "appearance"
3528
3615
  }
3529
3616
  ],
@@ -5379,6 +5466,14 @@ var ImageLightboxMeta = {
5379
5466
  description: "\uAE30\uBCF8 \uC378\uB124\uC77C <img>\uC5D0 \uBD99\uB294\uB2E4. \uCEE4\uC2A4\uD140 \uD2B8\uB9AC\uAC70(\uC790\uC2DD)\uB97C \uC8FC\uBA74 \uC4F0\uC774\uC9C0 \uC54A\uB294\uB2E4.",
5380
5467
  group: "layout",
5381
5468
  advanced: true
5469
+ },
5470
+ {
5471
+ name: "thumbStyle",
5472
+ kind: "object",
5473
+ label: "\uC378\uB124\uC77C \uC2A4\uD0C0\uC77C",
5474
+ description: '\uAE30\uBCF8 \uC378\uB124\uC77C <img>\uC5D0 \uC5B9\uB294 CSS \uC18D\uC131 \uAC1D\uCCB4(\uD06C\uAE30\xB7\uB9DE\uCDA4\xB7\uBAA8\uC11C\uB9AC \u2014 \uC608: {"width":96,"height":96,"objectFit":"cover"}). \uCEE4\uC2A4\uD140 \uD2B8\uB9AC\uAC70(\uC790\uC2DD)\uB97C \uC8FC\uBA74 \uC4F0\uC774\uC9C0 \uC54A\uB294\uB2E4. \uCEF4\uD3EC\uB10C\uD2B8 \uC790\uCCB4\uC758 \uD3ED\xB7\uC5EC\uBC31\uC740 \uC790\uAE30 \uCD95(width\xB7marginTop \u2026)\uC73C\uB85C.',
5475
+ group: "layout",
5476
+ advanced: true
5382
5477
  }
5383
5478
  ],
5384
5479
  children: { accepts: true, label: "\uCEE4\uC2A4\uD140 \uD2B8\uB9AC\uAC70 \u2014 \uC0DD\uB7B5\uD558\uBA74 \uAE30\uBCF8 \uC378\uB124\uC77C\uC774 \uADF8\uB824\uC9C4\uB2E4" },
@@ -5775,6 +5870,14 @@ var EventCalendarMeta = {
5775
5870
  description: "\uC8FC\uBA74 \uC81C\uC5B4 \uBAA8\uB4DC\uAC00 \uB41C\uB2E4.",
5776
5871
  group: "data",
5777
5872
  advanced: true
5873
+ },
5874
+ {
5875
+ name: "className",
5876
+ kind: "string",
5877
+ label: "\uCD94\uAC00 \uD074\uB798\uC2A4",
5878
+ description: "\uB2EC\uB825 \uBFCC\uB9AC \uC0C1\uC790\uC5D0 \uB367\uBD99\uB294\uB2E4 \u2014 \uC18C\uBE44 \uC571 \uC2DC\uD2B8\uAC00 \uB2EC\uB825 \uC548\uCABD\uC744 \uB2E4\uB4EC\uB294 \uD6C5 \uC790\uB9AC.",
5879
+ group: "layout",
5880
+ advanced: true
5778
5881
  }
5779
5882
  ],
5780
5883
  children: { accepts: false },
@@ -5964,7 +6067,7 @@ var TreeViewMeta = {
5964
6067
  kind: "string",
5965
6068
  label: "\uC120\uD0DD\uB41C \uB178\uB4DC id",
5966
6069
  bindable: true,
5967
- description: "\uC8FC\uBA74 \uC81C\uC5B4 \uBAA8\uB4DC\uAC00 \uB41C\uB2E4 \u2014 \uB0B4\uBD80 \uC120\uD0DD \uC0C1\uD0DC\uB97C \uC4F0\uC9C0 \uC54A\uB294\uB2E4.",
6070
+ description: "\uC8FC\uBA74 \uC81C\uC5B4 \uBAA8\uB4DC\uAC00 \uB41C\uB2E4 \u2014 \uB0B4\uBD80 \uC120\uD0DD \uC0C1\uD0DC\uB97C \uC4F0\uC9C0 \uC54A\uB294\uB2E4. \uAC12\uC774 \uBC14\uB00C\uBA74(\uB525\uB9C1\uD06C\xB7\uD558\uC704 \uD45C\uC5D0\uC11C \uB0B4\uB824\uAC10) \uC811\uD78C \uC870\uC0C1\uC744 \uD3BC\uCE58\uACE0 \uADF8 \uD589\uC744 \uD2B8\uB9AC \uC2A4\uD06C\uB864 \uC548\uC73C\uB85C \uAC00\uC838\uC628\uB2E4. \uAC19\uC740 \uC120\uD0DD\uC5D0\uC11C \uC0AC\uC6A9\uC790\uAC00 \uC811\uC740 \uAC83\uC740 \uADF8\uB300\uB85C \uB454\uB2E4.",
5968
6071
  group: "data"
5969
6072
  },
5970
6073
  { name: "onSelect", kind: "action", label: "\uB178\uB4DC \uC120\uD0DD", eventArg: "\uC120\uD0DD\uB41C \uB178\uB4DC id", group: "behavior" },
@@ -6213,7 +6316,16 @@ var SecureScreenMeta = {
6213
6316
  description: "false\uBA74 \uC544\uBB34 \uC81C\uC57D \uC5C6\uC774 \uC790\uC2DD\uC744 \uADF8\uB300\uB85C \uADF8\uB9B0\uB2E4.",
6214
6317
  group: "behavior"
6215
6318
  },
6216
- { name: "notice", kind: "string", label: "\uAC00\uB9BC\uB9C9 \uBB38\uAD6C", group: "content" }
6319
+ { name: "notice", kind: "string", label: "\uAC00\uB9BC\uB9C9 \uBB38\uAD6C", group: "content" },
6320
+ {
6321
+ name: "documentWideKeys",
6322
+ kind: "boolean",
6323
+ label: "\uBB38\uC11C \uC804\uCCB4 \uB2E8\uCD95\uD0A4 \uCC28\uB2E8",
6324
+ default: true,
6325
+ description: "Ctrl/Cmd+A\xB7C\xB7P\xB7S\xB7U\xB7X \uCC28\uB2E8\uC744 \uBB38\uC11C \uC804\uCCB4\uC5D0 \uAC74\uB2E4(\uB798\uD37C \uBC16\uC5D0\uC11C \uC804\uCCB4\uC120\uD0DD\u2192\uBCF5\uC0AC \uC6B0\uD68C\uB97C \uB9C9\uB294\uB2E4). \uD398\uC774\uC9C0 \uC77C\uBD80\uB9CC \uAC10\uC2F8\uB294 \uD654\uBA74\uC5D0\uC11C \uBCF4\uD638 \uB300\uC0C1 \uC544\uB2CC \uC785\uB825\uC758 \uBCF5\uC0AC\xB7\uC800\uC7A5\uAE4C\uC9C0 \uB9C9\uC9C0 \uC54A\uC73C\uB824\uBA74 \uB048\uB2E4 \u2014 \uADF8\uB54C\uB294 \uB798\uD37C \uC548\uC5D0\uC11C \uB204\uB978 \uC870\uD569\uB9CC \uB9C9\uB294\uB2E4.",
6326
+ group: "behavior",
6327
+ advanced: true
6328
+ }
6217
6329
  ],
6218
6330
  children: { accepts: true, text: true, label: "\uBCF4\uD638\uD560 \uB0B4\uC6A9" },
6219
6331
  dom: { element: "div" },
@@ -1,7 +1,7 @@
1
- import { loadOptionalModule } from '../chunk-NWYYNE3Q.js';
2
- import { useSduiAdapter, useSduiSandbox, hostFetchOf, defaultAdapter, hostRawFetchOf } from '../chunk-YNEEJCSZ.js';
1
+ import { loadOptionalModule } from '../chunk-4YPPL7JK.js';
2
+ import { useSduiAdapter, useSduiSandbox, hostFetchOf, defaultAdapter, hostRawFetchOf } from '../chunk-JHFA5RDN.js';
3
3
  import '../chunk-GSM664TX.js';
4
- import { Select, Input, Card, Button, Spinner, Icon, Alert, StatCard, Badge, Table, EmptyState } from '../chunk-BLFJMMBW.js';
4
+ import { Select, Input, Card, Button, Spinner, Icon, Alert, StatCard, Badge, Table, EmptyState } from '../chunk-YYAGE733.js';
5
5
  import { boxed } from '../chunk-3JTBOABA.js';
6
6
  import { useRef, useState, useMemo, useCallback } from 'react';
7
7
  import { jsx, jsxs } from 'react/jsx-runtime';
package/dist/rich.d.ts CHANGED
@@ -73,7 +73,8 @@ interface ChartProps {
73
73
  integer?: boolean;
74
74
  /**
75
75
  * x축 범주 라벨을 **모두** 보인다. 긴 라벨은 칸 폭에 맞춰 줄을 바꾸고(최대 3줄),
76
- * 그래도 모자라면 45° 기울인다. 칸이 그보다도 좁으면 겹치는 라벨만 건너뛴다(기본 동작).
76
+ * 그래도 모자라면 45° 기울인다(첫 라벨들이 왼쪽 밖으로 잘리지 않게 왼쪽 여백을 늘린다).
77
+ * 칸이 그보다도 좁으면 겹치는 라벨만 건너뛴다(기본 동작).
77
78
  * 끄면(기본) recharts가 겹치는 라벨을 건너뛴다 — 본부명처럼 긴 범주에서 라벨이 사라진다.
78
79
  */
79
80
  xTickWrap?: boolean;
package/dist/rich.js CHANGED
@@ -1,10 +1,10 @@
1
- import { useOptionalModule, DependencyPlaceholder } from './chunk-NWYYNE3Q.js';
2
- export { DatePicker, DateRangePicker, TimePicker } from './chunk-X2NIRVLN.js';
1
+ import { useOptionalModule, DependencyPlaceholder } from './chunk-4YPPL7JK.js';
2
+ export { DatePicker, DateRangePicker, TimePicker } from './chunk-FP32LNFK.js';
3
3
  import './chunk-BITS7UJY.js';
4
4
  import { HoistedStyle } from './chunk-RIZRM7OO.js';
5
- import { useSduiAssetResolver } from './chunk-YNEEJCSZ.js';
5
+ import { useSduiAssetResolver } from './chunk-JHFA5RDN.js';
6
6
  import './chunk-GSM664TX.js';
7
- import { Spinner, EmptyState } from './chunk-BLFJMMBW.js';
7
+ import { Spinner, EmptyState } from './chunk-YYAGE733.js';
8
8
  import './chunk-3JTBOABA.js';
9
9
  import { useRef, useCallback, useMemo, useState, useEffect, useLayoutEffect } from 'react';
10
10
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -182,6 +182,31 @@ function planXTicks(labels, bandWidth, measure) {
182
182
  }
183
183
  return { mode: "skip" };
184
184
  }
185
+ var ROTATE_EDGE_PAD = 2;
186
+ function rotatedTickInset(widths, axisWidth, span, point = false) {
187
+ const n = widths.length;
188
+ if (n === 0 || !(span > 0)) return 0;
189
+ let inset = 0;
190
+ widths.forEach((width, i) => {
191
+ const f = point ? n > 1 ? i / (n - 1) : 0.5 : (i + 0.5) / n;
192
+ if (f >= 1) return;
193
+ const reach = (width + TICK_FONT / 2) * Math.SQRT1_2 + ROTATE_EDGE_PAD;
194
+ const need = (reach - axisWidth - span * f) / (1 - f);
195
+ if (need > inset) inset = need;
196
+ });
197
+ return Math.ceil(inset);
198
+ }
199
+ var ROTATE_MIN_BAND = TICK_FONT * 1.25 / Math.SQRT1_2;
200
+ function planXTicksWithInset(labels, span, axisWidth, measure, point = false) {
201
+ const count = Math.max(1, labels.length);
202
+ const plan = planXTicks(labels, span / count, measure);
203
+ if (plan.mode !== "rotate") return { plan, inset: 0 };
204
+ const want = rotatedTickInset(labels.map((label) => measure(label)), axisWidth, span, point);
205
+ const inset = Math.max(0, Math.min(want, Math.floor(span - count * ROTATE_MIN_BAND)));
206
+ if (inset === 0) return { plan, inset: 0 };
207
+ const narrowed = planXTicks(labels, (span - inset) / count, measure);
208
+ return narrowed.mode === "rotate" ? { plan: narrowed, inset } : { plan, inset: 0 };
209
+ }
185
210
  var tooltipBoxStyle = {
186
211
  background: "var(--wp-surface-card)",
187
212
  border: "1px solid var(--wp-border-subtle)",
@@ -614,8 +639,10 @@ function Chart({
614
639
  let xTick = {};
615
640
  if (xTickWrap && hostBox.width > 0) {
616
641
  const labels = rows.map((row) => String((xKey ? row[xKey] : void 0) ?? ""));
617
- const plotWidth = hostBox.width - margin.left - margin.right - Y_AXIS_WIDTH * (dual ? 2 : 1);
618
- const plan = planXTicks(labels, plotWidth / Math.max(1, labels.length), makeMeasure(hostBox.fontFamily));
642
+ const measure = makeMeasure(hostBox.fontFamily);
643
+ const span = hostBox.width - margin.right - Y_AXIS_WIDTH * (dual ? 2 : 1);
644
+ const { plan, inset } = planXTicksWithInset(labels, span - margin.left, Y_AXIS_WIDTH, measure, !hasBar);
645
+ margin.left += inset;
619
646
  if (plan.mode !== "skip") {
620
647
  xTick = { interval: 0, height: plan.height, tick: renderCategoryTick(plan) };
621
648
  }