@simplysm/solid 13.0.62 → 13.0.64

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 (86) hide show
  1. package/README.md +6 -0
  2. package/dist/components/data/crud-detail/CrudDetail.d.ts.map +1 -1
  3. package/dist/components/data/crud-detail/CrudDetail.js +62 -41
  4. package/dist/components/data/crud-detail/CrudDetail.js.map +2 -2
  5. package/dist/components/data/crud-sheet/CrudSheet.d.ts.map +1 -1
  6. package/dist/components/data/crud-sheet/CrudSheet.js +164 -19
  7. package/dist/components/data/crud-sheet/CrudSheet.js.map +2 -2
  8. package/dist/components/data/crud-sheet/types.d.ts +9 -3
  9. package/dist/components/data/crud-sheet/types.d.ts.map +1 -1
  10. package/dist/components/data/sheet/DataSheet.d.ts.map +1 -1
  11. package/dist/components/data/sheet/DataSheet.js +3 -2
  12. package/dist/components/data/sheet/DataSheet.js.map +2 -2
  13. package/dist/components/form-control/checkbox/Checkbox.d.ts.map +1 -1
  14. package/dist/components/form-control/checkbox/Checkbox.js +10 -10
  15. package/dist/components/form-control/checkbox/Checkbox.js.map +2 -2
  16. package/dist/components/form-control/checkbox/Checkbox.styles.d.ts.map +1 -1
  17. package/dist/components/form-control/checkbox/Checkbox.styles.js +2 -2
  18. package/dist/components/form-control/checkbox/Checkbox.styles.js.map +1 -1
  19. package/dist/components/form-control/checkbox/Radio.d.ts.map +1 -1
  20. package/dist/components/form-control/checkbox/Radio.js +13 -13
  21. package/dist/components/form-control/checkbox/Radio.js.map +2 -2
  22. package/dist/components/form-control/data-select-button/DataSelectButton.d.ts +38 -0
  23. package/dist/components/form-control/data-select-button/DataSelectButton.d.ts.map +1 -0
  24. package/dist/components/form-control/data-select-button/DataSelectButton.js +184 -0
  25. package/dist/components/form-control/data-select-button/DataSelectButton.js.map +6 -0
  26. package/dist/components/form-control/select/Select.d.ts +7 -3
  27. package/dist/components/form-control/select/Select.d.ts.map +1 -1
  28. package/dist/components/form-control/select/Select.js +146 -45
  29. package/dist/components/form-control/select/Select.js.map +2 -2
  30. package/dist/components/form-control/select-list/SelectList.d.ts +54 -0
  31. package/dist/components/form-control/select-list/SelectList.d.ts.map +1 -0
  32. package/dist/components/form-control/select-list/SelectList.js +280 -0
  33. package/dist/components/form-control/select-list/SelectList.js.map +6 -0
  34. package/dist/components/form-control/select-list/SelectListContext.d.ts +13 -0
  35. package/dist/components/form-control/select-list/SelectListContext.d.ts.map +1 -0
  36. package/dist/components/form-control/select-list/SelectListContext.js +14 -0
  37. package/dist/components/form-control/select-list/SelectListContext.js.map +6 -0
  38. package/dist/components/form-control/shared-data/SharedDataSelect.d.ts +32 -0
  39. package/dist/components/form-control/shared-data/SharedDataSelect.d.ts.map +1 -0
  40. package/dist/components/form-control/shared-data/SharedDataSelect.js +74 -0
  41. package/dist/components/form-control/shared-data/SharedDataSelect.js.map +6 -0
  42. package/dist/components/form-control/shared-data/SharedDataSelectButton.d.ts +29 -0
  43. package/dist/components/form-control/shared-data/SharedDataSelectButton.d.ts.map +1 -0
  44. package/dist/components/form-control/shared-data/SharedDataSelectButton.js +17 -0
  45. package/dist/components/form-control/shared-data/SharedDataSelectButton.js.map +6 -0
  46. package/dist/components/form-control/shared-data/SharedDataSelectList.d.ts +29 -0
  47. package/dist/components/form-control/shared-data/SharedDataSelectList.d.ts.map +1 -0
  48. package/dist/components/form-control/shared-data/SharedDataSelectList.js +80 -0
  49. package/dist/components/form-control/shared-data/SharedDataSelectList.js.map +6 -0
  50. package/dist/features/address/AddressSearch.d.ts +8 -0
  51. package/dist/features/address/AddressSearch.d.ts.map +1 -0
  52. package/dist/features/address/AddressSearch.js +72 -0
  53. package/dist/features/address/AddressSearch.js.map +6 -0
  54. package/dist/index.d.ts +6 -0
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +6 -0
  57. package/dist/index.js.map +1 -1
  58. package/dist/providers/shared-data/SharedDataContext.d.ts +14 -0
  59. package/dist/providers/shared-data/SharedDataContext.d.ts.map +1 -1
  60. package/dist/providers/shared-data/SharedDataContext.js.map +1 -1
  61. package/dist/providers/shared-data/SharedDataProvider.d.ts.map +1 -1
  62. package/dist/providers/shared-data/SharedDataProvider.js +5 -1
  63. package/dist/providers/shared-data/SharedDataProvider.js.map +2 -2
  64. package/docs/data-components.md +15 -4
  65. package/docs/form-controls.md +257 -0
  66. package/docs/hooks.md +30 -0
  67. package/docs/providers.md +7 -0
  68. package/package.json +3 -3
  69. package/src/components/data/crud-detail/CrudDetail.tsx +51 -26
  70. package/src/components/data/crud-sheet/CrudSheet.tsx +157 -20
  71. package/src/components/data/crud-sheet/types.ts +13 -3
  72. package/src/components/data/sheet/DataSheet.tsx +6 -7
  73. package/src/components/form-control/checkbox/Checkbox.styles.ts +2 -2
  74. package/src/components/form-control/checkbox/Checkbox.tsx +18 -20
  75. package/src/components/form-control/checkbox/Radio.tsx +18 -20
  76. package/src/components/form-control/data-select-button/DataSelectButton.tsx +279 -0
  77. package/src/components/form-control/select/Select.tsx +192 -36
  78. package/src/components/form-control/select-list/SelectList.tsx +385 -0
  79. package/src/components/form-control/select-list/SelectListContext.ts +23 -0
  80. package/src/components/form-control/shared-data/SharedDataSelect.tsx +101 -0
  81. package/src/components/form-control/shared-data/SharedDataSelectButton.tsx +47 -0
  82. package/src/components/form-control/shared-data/SharedDataSelectList.tsx +85 -0
  83. package/src/features/address/AddressSearch.tsx +75 -0
  84. package/src/index.ts +18 -0
  85. package/src/providers/shared-data/SharedDataContext.ts +14 -0
  86. package/src/providers/shared-data/SharedDataProvider.tsx +4 -0
@@ -11,7 +11,8 @@ import {
11
11
  } from "solid-js";
12
12
  import { createStore, produce, reconcile } from "solid-js/store";
13
13
  import { createControllableStore } from "../../../hooks/createControllableStore";
14
- import { objClone } from "@simplysm/core-common";
14
+ import type { DateTime } from "@simplysm/core-common";
15
+ import { objClone, objGetChainValue } from "@simplysm/core-common";
15
16
  import "@simplysm/core-common"; // register extensions
16
17
  import type { SortingDef } from "../sheet/types";
17
18
  import { DataSheet } from "../sheet/DataSheet";
@@ -26,6 +27,7 @@ import { useDialogInstance } from "../../disclosure/DialogInstanceContext";
26
27
  import { Dialog } from "../../disclosure/Dialog";
27
28
  import { Link } from "../../display/Link";
28
29
  import { createEventListener } from "@solid-primitives/event-listener";
30
+ import { useBeforeLeave } from "@solidjs/router";
29
31
  import clsx from "clsx";
30
32
  import {
31
33
  IconDeviceFloppy,
@@ -67,11 +69,14 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
67
69
  "search",
68
70
  "getItemKey",
69
71
  "persistKey",
70
- "itemsPerPage",
71
72
  "editable",
72
73
  "itemEditable",
73
74
  "itemDeletable",
74
75
  "itemDeleted",
76
+ "isItemSelectable",
77
+ "lastModifiedAtProp",
78
+ "lastModifiedByProp",
79
+ "onSubmitted",
75
80
  "filterInitial",
76
81
  "items",
77
82
  "onItemsChange",
@@ -123,6 +128,7 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
123
128
  const [ready, setReady] = createSignal(false);
124
129
 
125
130
  const [selectedItems, setSelectedItems] = createSignal<TItem[]>([]);
131
+ const [selectedKeys, setSelectedKeys] = createSignal<Set<string | number>>(new Set());
126
132
 
127
133
  let formRef: HTMLFormElement | undefined;
128
134
 
@@ -130,6 +136,23 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
130
136
  void doRefresh();
131
137
  });
132
138
 
139
+ // -- Key-based selection: restore selectedItems when items change --
140
+ createEffect(() => {
141
+ const currentItems = items as unknown as TItem[];
142
+ const keys = selectedKeys();
143
+ if (keys.size === 0) {
144
+ if (selectedItems().length > 0) {
145
+ setSelectedItems([]);
146
+ }
147
+ return;
148
+ }
149
+ const restored = currentItems.filter((item) => {
150
+ const key = local.getItemKey(item);
151
+ return key != null && keys.has(key);
152
+ });
153
+ setSelectedItems(restored);
154
+ });
155
+
133
156
  async function doRefresh() {
134
157
  setBusyCount((c) => c + 1);
135
158
  try {
@@ -142,12 +165,7 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
142
165
  }
143
166
 
144
167
  async function refresh() {
145
- const usePagination = local.itemsPerPage != null;
146
- const result: SearchResult<TItem> = await local.search(
147
- lastFilter(),
148
- usePagination ? page() : 0,
149
- sorts(),
150
- );
168
+ const result: SearchResult<TItem> = await local.search(lastFilter(), page(), sorts());
151
169
  setItems(reconcile(result.items));
152
170
  originalItems = objClone(result.items);
153
171
  setTotalPageCount(result.pageCount ?? 0);
@@ -155,20 +173,28 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
155
173
 
156
174
  /* eslint-disable solid/reactivity -- 이벤트 핸들러에서만 호출, store 즉시 읽기 */
157
175
  function getItemDiffs() {
158
- return (items as unknown as TItem[]).oneWayDiffs(originalItems, ((item: TItem) => {
159
- return local.getItemKey(item);
160
- }) as (item: TItem) => keyof TItem);
176
+ return items.oneWayDiffs(originalItems, (item) => local.getItemKey(item), {
177
+ excludes: local.inlineEdit?.diffsExcludes,
178
+ });
161
179
  }
162
180
  /* eslint-enable solid/reactivity */
163
181
 
182
+ function checkIgnoreChanges(): boolean {
183
+ if (!local.inlineEdit) return true;
184
+ if (getItemDiffs().length === 0) return true;
185
+ return confirm("변경사항이 있습니다. 무시하시겠습니까?");
186
+ }
187
+
164
188
  // -- Filter --
165
189
  function handleFilterSubmit(e: Event) {
166
190
  e.preventDefault();
191
+ if (!checkIgnoreChanges()) return;
167
192
  setPage(1);
168
193
  setLastFilter(() => objClone(filter));
169
194
  }
170
195
 
171
196
  async function handleRefresh() {
197
+ if (!checkIgnoreChanges()) return;
172
198
  await doRefresh();
173
199
  }
174
200
 
@@ -216,6 +242,7 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
216
242
  await local.inlineEdit.submit(diffs);
217
243
  noti.success("저장 완료", "저장되었습니다.");
218
244
  await refresh();
245
+ local.onSubmitted?.();
219
246
  } catch (err) {
220
247
  noti.error(err, "저장 실패");
221
248
  }
@@ -257,13 +284,28 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
257
284
  setBusyCount((c) => c - 1);
258
285
  }
259
286
 
287
+ async function handleRestoreItems() {
288
+ if (!local.modalEdit?.restoreItems) return;
289
+ const result = await local.modalEdit.restoreItems(selectedItems());
290
+ if (!result) return;
291
+
292
+ setBusyCount((c) => c + 1);
293
+ try {
294
+ await refresh();
295
+ noti.success("복구 완료", "복구되었습니다.");
296
+ } catch (err) {
297
+ noti.error(err, "복구 실패");
298
+ }
299
+ setBusyCount((c) => c - 1);
300
+ }
301
+
260
302
  // -- Excel --
261
303
  async function handleExcelDownload() {
262
304
  if (!local.excel) return;
263
305
 
264
306
  setBusyCount((c) => c + 1);
265
307
  try {
266
- const result = await local.search(lastFilter(), 0, sorts());
308
+ const result = await local.search(lastFilter(), undefined, sorts());
267
309
  await local.excel.download(result.items);
268
310
  } catch (err) {
269
311
  noti.error(err, "엑셀 다운로드 실패");
@@ -295,16 +337,51 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
295
337
  }
296
338
 
297
339
  // -- Select Mode --
340
+ function handleSelectedItemsChange(newSelectedItems: TItem[]) {
341
+ // 현재 페이지 아이템들의 key Set
342
+ const currentItems = items as unknown as TItem[];
343
+ const currentKeys = new Set<string | number>();
344
+ for (const item of currentItems) {
345
+ const key = local.getItemKey(item);
346
+ if (key != null) currentKeys.add(key);
347
+ }
348
+
349
+ // 새로 선택된 아이템들의 key
350
+ const newSelectedKeys = new Set<string | number>();
351
+ for (const item of newSelectedItems) {
352
+ const key = local.getItemKey(item);
353
+ if (key != null) newSelectedKeys.add(key);
354
+ }
355
+
356
+ // 다른 페이지 key 보존 + 현재 페이지 key 갱신
357
+ const merged = new Set<string | number>();
358
+ for (const key of selectedKeys()) {
359
+ if (!currentKeys.has(key)) {
360
+ merged.add(key); // 다른 페이지 key 보존
361
+ }
362
+ }
363
+ for (const key of newSelectedKeys) {
364
+ merged.add(key); // 현재 페이지 선택 추가
365
+ }
366
+
367
+ setSelectedKeys(merged);
368
+ setSelectedItems(newSelectedItems);
369
+ }
370
+
371
+ function clearSelection() {
372
+ setSelectedKeys(new Set<string | number>());
373
+ setSelectedItems([]);
374
+ }
375
+
298
376
  function handleSelectConfirm() {
299
377
  local.onSelect?.({
300
378
  items: selectedItems(),
301
- keys: selectedItems()
302
- .map((item) => local.getItemKey(item))
303
- .filter((k): k is string | number => k != null),
379
+ keys: [...selectedKeys()],
304
380
  });
305
381
  }
306
382
 
307
383
  function handleSelectCancel() {
384
+ clearSelection();
308
385
  local.onSelect?.({ items: [], keys: [] });
309
386
  }
310
387
 
@@ -316,10 +393,25 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
316
393
  }
317
394
  if (e.ctrlKey && e.altKey && e.key === "l") {
318
395
  e.preventDefault();
396
+ if (!checkIgnoreChanges()) return;
319
397
  await doRefresh();
320
398
  }
321
399
  });
322
400
 
401
+ // -- Route Leave Guard --
402
+ // eslint-disable-next-line solid/reactivity -- inlineEdit는 초기 설정값으로만 사용
403
+ if (!isModal && local.inlineEdit) {
404
+ try {
405
+ useBeforeLeave((e) => {
406
+ if (!checkIgnoreChanges()) {
407
+ e.preventDefault();
408
+ }
409
+ });
410
+ } catch {
411
+ // Router context 없으면 skip
412
+ }
413
+ }
414
+
323
415
  // -- Topbar Actions --
324
416
  if (topbarCtx) {
325
417
  createTopbarActions(() => (
@@ -361,6 +453,7 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
361
453
  addItem: handleAddRow,
362
454
  setPage,
363
455
  setSorts,
456
+ clearSelection,
364
457
  };
365
458
 
366
459
  // -- Render --
@@ -458,13 +551,32 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
458
551
  onClick={handleDeleteItems}
459
552
  disabled={
460
553
  selectedItems().length === 0 ||
461
- !selectedItems().some((item) => local.itemDeletable?.(item) ?? true)
554
+ !selectedItems().some(
555
+ (item) =>
556
+ (local.itemDeletable?.(item) ?? true) &&
557
+ !(local.itemDeleted?.(item) ?? false),
558
+ )
462
559
  }
463
560
  >
464
561
  <Icon icon={IconTrash} class="mr-1" />
465
562
  선택 삭제
466
563
  </Button>
467
564
  </Show>
565
+ <Show when={canEdit() && local.modalEdit?.restoreItems}>
566
+ <Button
567
+ size="sm"
568
+ theme="warning"
569
+ variant="ghost"
570
+ onClick={handleRestoreItems}
571
+ disabled={
572
+ selectedItems().length === 0 ||
573
+ !selectedItems().some((item) => local.itemDeleted?.(item) ?? false)
574
+ }
575
+ >
576
+ <Icon icon={IconTrashOff} class="mr-1" />
577
+ 선택 복구
578
+ </Button>
579
+ </Show>
468
580
 
469
581
  {/* Excel buttons */}
470
582
  <Show when={canEdit() && local.excel?.upload}>
@@ -492,21 +604,21 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
492
604
  class="h-full"
493
605
  items={items}
494
606
  persistKey={local.persistKey != null ? `${local.persistKey}-sheet` : undefined}
495
- page={local.itemsPerPage != null ? page() : undefined}
607
+ page={totalPageCount() > 0 ? page() : undefined}
496
608
  onPageChange={setPage}
497
609
  totalPageCount={totalPageCount()}
498
- itemsPerPage={local.itemsPerPage}
499
610
  sorts={sorts()}
500
611
  onSortsChange={setSorts}
612
+ isItemSelectable={local.isItemSelectable}
501
613
  selectMode={
502
614
  isSelectMode()
503
615
  ? local.selectMode
504
- : local.modalEdit?.deleteItems != null
616
+ : local.modalEdit?.deleteItems != null || local.modalEdit?.restoreItems != null
505
617
  ? "multiple"
506
618
  : undefined
507
619
  }
508
620
  selectedItems={selectedItems()}
509
- onSelectedItemsChange={setSelectedItems}
621
+ onSelectedItemsChange={handleSelectedItemsChange}
510
622
  autoSelect={isSelectMode() && local.selectMode === "single" ? "click" : undefined}
511
623
  cellClass={(item) => {
512
624
  if (isItemDeleted(item)) {
@@ -593,6 +705,31 @@ const CrudSheetBase = <TItem, TFilter extends Record<string, any>>(
593
705
  </DataSheetColumn>
594
706
  )}
595
707
  </For>
708
+
709
+ {/* Auto lastModified columns */}
710
+ <Show when={local.lastModifiedAtProp}>
711
+ <DataSheetColumn<TItem> key={local.lastModifiedAtProp!} header="수정일시" hidden>
712
+ {(dsCtx) => (
713
+ <div class="px-2 py-1 text-center">
714
+ {(
715
+ objGetChainValue(dsCtx.item, local.lastModifiedAtProp!, true) as
716
+ | DateTime
717
+ | undefined
718
+ )?.toFormatString("yyyy-MM-dd HH:mm")}
719
+ </div>
720
+ )}
721
+ </DataSheetColumn>
722
+ </Show>
723
+
724
+ <Show when={local.lastModifiedByProp}>
725
+ <DataSheetColumn<TItem> key={local.lastModifiedByProp!} header="수정자" hidden>
726
+ {(dsCtx) => (
727
+ <div class="px-2 py-1 text-center">
728
+ {objGetChainValue(dsCtx.item, local.lastModifiedByProp!, true) as string}
729
+ </div>
730
+ )}
731
+ </DataSheetColumn>
732
+ </Show>
596
733
  </DataSheet>
597
734
  </form>
598
735
 
@@ -16,11 +16,13 @@ export interface InlineEditConfig<TItem> {
16
16
  submit: (diffs: ArrayDiffs2Result<TItem>[]) => Promise<void>;
17
17
  newItem: () => TItem;
18
18
  deleteProp?: keyof TItem & string;
19
+ diffsExcludes?: string[];
19
20
  }
20
21
 
21
22
  export interface ModalEditConfig<TItem> {
22
- editItem: (item?: TItem) => Promise<boolean>;
23
+ editItem: (item?: TItem) => Promise<boolean | undefined>;
23
24
  deleteItems?: (items: TItem[]) => Promise<boolean>;
25
+ restoreItems?: (items: TItem[]) => Promise<boolean>;
24
26
  }
25
27
 
26
28
  export interface ExcelConfig<TItem> {
@@ -56,6 +58,7 @@ export interface CrudSheetContext<TItem> {
56
58
  save(): Promise<void>;
57
59
  refresh(): Promise<void>;
58
60
  addItem(): void;
61
+ clearSelection(): void;
59
62
  setPage(page: number): void;
60
63
  setSorts(sorts: SortingDef[]): void;
61
64
  }
@@ -73,20 +76,27 @@ export type CrudSheetProps<TItem, TFilter extends Record<string, any>> = CrudShe
73
76
  );
74
77
 
75
78
  interface CrudSheetBaseProps<TItem, TFilter extends Record<string, any>> {
76
- search: (filter: TFilter, page: number, sorts: SortingDef[]) => Promise<SearchResult<TItem>>;
79
+ search: (
80
+ filter: TFilter,
81
+ page: number | undefined,
82
+ sorts: SortingDef[],
83
+ ) => Promise<SearchResult<TItem>>;
77
84
  getItemKey: (item: TItem) => string | number | undefined;
78
85
  persistKey?: string;
79
- itemsPerPage?: number;
80
86
  editable?: boolean;
81
87
  itemEditable?: (item: TItem) => boolean;
82
88
  itemDeletable?: (item: TItem) => boolean;
83
89
  itemDeleted?: (item: TItem) => boolean;
90
+ isItemSelectable?: (item: TItem) => boolean | string;
91
+ lastModifiedAtProp?: string;
92
+ lastModifiedByProp?: string;
84
93
  filterInitial?: TFilter;
85
94
  items?: TItem[];
86
95
  onItemsChange?: (items: TItem[]) => void;
87
96
  excel?: ExcelConfig<TItem>;
88
97
  selectMode?: "single" | "multiple";
89
98
  onSelect?: (result: SelectResult<TItem>) => void;
99
+ onSubmitted?: () => void;
90
100
  hideAutoTools?: boolean;
91
101
  class?: string;
92
102
  children: JSX.Element;
@@ -114,10 +114,8 @@ export const DataSheet: DataSheetComponent = <T,>(props: DataSheetProps<T>) => {
114
114
 
115
115
  // #region Column Collection
116
116
  const resolved = children(() => local.children);
117
- const columnDefs = createMemo(() =>
118
- (resolved.toArray().filter(isDataSheetColumnDef) as unknown as DataSheetColumnDef<T>[]).filter(
119
- (col) => !col.hidden,
120
- ),
117
+ const columnDefs = createMemo(
118
+ () => resolved.toArray().filter(isDataSheetColumnDef) as unknown as DataSheetColumnDef<T>[],
121
119
  );
122
120
 
123
121
  // #region Config (useSyncConfig)
@@ -130,14 +128,15 @@ export const DataSheet: DataSheetComponent = <T,>(props: DataSheetProps<T>) => {
130
128
 
131
129
  // 설정이 적용된 최종 컬럼 — config의 hidden/fixed/width/displayOrder 오버라이드 적용
132
130
  const effectiveColumns = createMemo(() => {
133
- const cols = columnDefs(); // 이미 col.hidden (코드 설정) 필터링됨
131
+ const cols = columnDefs();
134
132
  const record = config().columnRecord ?? {};
135
133
 
136
134
  return cols
137
135
  .filter((col) => {
138
- // config에서 hidden으로 설정된 컬럼 제외
136
+ // config 오버라이드가 있으면 config 우선, 없으면 원래 col.hidden 사용
139
137
  const saved = record[col.key];
140
- return !saved?.hidden;
138
+ const isHidden = saved?.hidden ?? col.hidden;
139
+ return !isHidden;
141
140
  })
142
141
  .map((col) => {
143
142
  const saved = record[col.key];
@@ -1,6 +1,5 @@
1
1
  import clsx from "clsx";
2
2
  import {
3
- bgSurface,
4
3
  borderDefault,
5
4
  type ComponentSize,
6
5
  disabledOpacity,
@@ -32,7 +31,8 @@ export const indicatorBaseClass = clsx(
32
31
  "size-4",
33
32
  "border",
34
33
  borderDefault,
35
- bgSurface,
34
+ // bgSurface,
35
+ "bg-primary-50 dark:bg-primary-950/30",
36
36
  "transition-colors",
37
37
  );
38
38
 
@@ -90,27 +90,25 @@ export const Checkbox: ParentComponent<CheckboxProps> = (props) => {
90
90
 
91
91
  return (
92
92
  <Invalid message={errorMsg()} variant="border" touchMode={local.touchMode}>
93
- <div class="inline-flex">
94
- <label
95
- {...rest}
96
- use:ripple={!local.disabled}
97
- role="checkbox"
98
- aria-checked={value()}
99
- tabIndex={local.disabled ? -1 : 0}
100
- class={getWrapperClass()}
101
- style={local.style}
102
- onClick={handleClick}
103
- onKeyDown={handleKeyDown}
104
- >
105
- <div class={getIndicatorClass()}>
106
- <Show when={value()}>
107
- <Icon icon={IconCheck} size="1em" />
108
- </Show>
109
- </div>
110
- <Show when={local.children}>
111
- <span>{local.children}</span>
93
+ <div
94
+ {...rest}
95
+ use:ripple={!local.disabled}
96
+ role="checkbox"
97
+ aria-checked={value()}
98
+ tabIndex={local.disabled ? -1 : 0}
99
+ class={getWrapperClass()}
100
+ style={local.style}
101
+ onClick={handleClick}
102
+ onKeyDown={handleKeyDown}
103
+ >
104
+ <div class={getIndicatorClass()}>
105
+ <Show when={value()}>
106
+ <Icon icon={IconCheck} size="1em" />
112
107
  </Show>
113
- </label>
108
+ </div>
109
+ <Show when={local.children}>
110
+ <span>{local.children}</span>
111
+ </Show>
114
112
  </div>
115
113
  </Invalid>
116
114
  );
@@ -91,27 +91,25 @@ export const Radio: ParentComponent<RadioProps> = (props) => {
91
91
 
92
92
  return (
93
93
  <Invalid message={errorMsg()} variant="border" touchMode={local.touchMode}>
94
- <div class="inline-flex">
95
- <label
96
- {...rest}
97
- use:ripple={!local.disabled}
98
- role="radio"
99
- aria-checked={value()}
100
- tabIndex={local.disabled ? -1 : 0}
101
- class={getWrapperClass()}
102
- style={local.style}
103
- onClick={handleClick}
104
- onKeyDown={handleKeyDown}
105
- >
106
- <div class={getIndicatorClass()}>
107
- <Show when={value()}>
108
- <div class={radioDotClass} />
109
- </Show>
110
- </div>
111
- <Show when={local.children}>
112
- <span>{local.children}</span>
94
+ <div
95
+ {...rest}
96
+ use:ripple={!local.disabled}
97
+ role="radio"
98
+ aria-checked={value()}
99
+ tabIndex={local.disabled ? -1 : 0}
100
+ class={getWrapperClass()}
101
+ style={local.style}
102
+ onClick={handleClick}
103
+ onKeyDown={handleKeyDown}
104
+ >
105
+ <div class={getIndicatorClass()}>
106
+ <Show when={value()}>
107
+ <div class={radioDotClass} />
113
108
  </Show>
114
- </label>
109
+ </div>
110
+ <Show when={local.children}>
111
+ <span>{local.children}</span>
112
+ </Show>
115
113
  </div>
116
114
  </Invalid>
117
115
  );