sellmate-design-system-react 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/AGENTS.md +695 -0
  2. package/README.md +106 -0
  3. package/bin/sellmate-ds.mjs +337 -0
  4. package/dist/components/SActionModal/README.md +41 -0
  5. package/dist/components/SBadge/README.md +25 -0
  6. package/dist/components/SBarcodeInput/README.md +64 -0
  7. package/dist/components/SButton/README.md +49 -0
  8. package/dist/components/SCalendar/README.md +42 -0
  9. package/dist/components/SCallout/README.md +29 -0
  10. package/dist/components/SCard/README.md +12 -0
  11. package/dist/components/SCheckbox/README.md +44 -0
  12. package/dist/components/SChip/README.md +57 -0
  13. package/dist/components/SChipInput/README.md +77 -0
  14. package/dist/components/SCircleProgress/README.md +35 -0
  15. package/dist/components/SConfirmModal/README.md +61 -0
  16. package/dist/components/SDatePicker/README.md +62 -0
  17. package/dist/components/SDateRangePicker/README.md +64 -0
  18. package/dist/components/SDivider/README.md +25 -0
  19. package/dist/components/SDraggableItem/README.md +40 -0
  20. package/dist/components/SDropdownButton/README.md +50 -0
  21. package/dist/components/SExpansionItem/README.md +40 -0
  22. package/dist/components/SField/README.md +91 -0
  23. package/dist/components/SFilePicker/README.md +72 -0
  24. package/dist/components/SForm/README.md +31 -0
  25. package/dist/components/SGhostButton/README.md +76 -0
  26. package/dist/components/SGnb/README.md +56 -0
  27. package/dist/components/SGuide/README.md +34 -0
  28. package/dist/components/SIcon/README.md +91 -0
  29. package/dist/components/SInput/README.md +66 -0
  30. package/dist/components/SKeyValueTable/README.md +59 -0
  31. package/dist/components/SLayout/README.md +42 -0
  32. package/dist/components/SLinearProgress/README.md +17 -0
  33. package/dist/components/SList/README.md +14 -0
  34. package/dist/components/SListItem/README.md +19 -0
  35. package/dist/components/SLoadingContainer/README.md +29 -0
  36. package/dist/components/SLoadingModal/README.md +52 -0
  37. package/dist/components/SModal/README.md +192 -0
  38. package/dist/components/SModalContainer/README.md +49 -0
  39. package/dist/components/SNumberInput/README.md +74 -0
  40. package/dist/components/SPage/README.md +25 -0
  41. package/dist/components/SPagination/README.md +40 -0
  42. package/dist/components/SPopover/README.md +54 -0
  43. package/dist/components/SPopup/README.md +38 -0
  44. package/dist/components/SPortal/README.md +51 -0
  45. package/dist/components/SRadio/README.md +57 -0
  46. package/dist/components/SRadioButton/README.md +24 -0
  47. package/dist/components/SScrollArea/README.md +16 -0
  48. package/dist/components/SSectionHeaderCard/README.md +51 -0
  49. package/dist/components/SSelect/README.md +79 -0
  50. package/dist/components/SStepper/README.md +30 -0
  51. package/dist/components/SSwitch/README.md +24 -0
  52. package/dist/components/STable/README.md +82 -0
  53. package/dist/components/STableBar/README.md +28 -0
  54. package/dist/components/STabs/README.md +37 -0
  55. package/dist/components/STag/README.md +44 -0
  56. package/dist/components/STextLink/README.md +48 -0
  57. package/dist/components/STextarea/README.md +60 -0
  58. package/dist/components/STimePicker/README.md +65 -0
  59. package/dist/components/STimeRangePicker/README.md +63 -0
  60. package/dist/components/SToast/README.md +70 -0
  61. package/dist/components/SToggle/README.md +22 -0
  62. package/dist/components/STooltip/README.md +57 -0
  63. package/dist/llms-full.txt +3530 -0
  64. package/dist/llms.txt +882 -0
  65. package/dist/styles.css +221 -0
  66. package/dist/theme.css +8 -0
  67. package/eslint/index.mjs +69 -0
  68. package/eslint/lib/class-names.mjs +119 -0
  69. package/eslint/lib/table-column.mjs +53 -0
  70. package/eslint/rules/component-group-gap.mjs +186 -0
  71. package/eslint/rules/no-arbitrary-class.mjs +91 -0
  72. package/eslint/rules/no-off-scale-spacing.mjs +67 -0
  73. package/eslint/rules/no-raw-html-control.mjs +117 -0
  74. package/eslint/rules/prefer-typo-preset.mjs +73 -0
  75. package/eslint/rules/require-locale-number.mjs +78 -0
  76. package/eslint/rules/table-numeric-align.mjs +93 -0
  77. package/eslint/scale.gen.mjs +16 -0
  78. package/package.json +15 -4
package/dist/styles.css CHANGED
@@ -31,6 +31,9 @@
31
31
  --text-base--line-height: calc(1.5 / 1);
32
32
  --text-xl: 1.25rem;
33
33
  --text-xl--line-height: calc(1.75 / 1.25);
34
+ --font-weight-thin: 100;
35
+ --font-weight-extralight: 200;
36
+ --font-weight-light: 300;
34
37
  --font-weight-normal: 400;
35
38
  --font-weight-medium: 500;
36
39
  --font-weight-semibold: 600;
@@ -669,6 +672,9 @@
669
672
  .top-\[16px\] {
670
673
  top: 16px;
671
674
  }
675
+ .top-\[64px\] {
676
+ top: 64px;
677
+ }
672
678
  .top-\[var\(--cmp-table-header-height\)\] {
673
679
  top: var(--cmp-table-header-height);
674
680
  }
@@ -747,6 +753,9 @@
747
753
  .z-\[31\] {
748
754
  z-index: 31;
749
755
  }
756
+ .z-\[60\] {
757
+ z-index: 60;
758
+ }
750
759
  .z-\[1000\] {
751
760
  z-index: 1000;
752
761
  }
@@ -789,6 +798,9 @@
789
798
  .mx-3 {
790
799
  margin-inline: calc(var(--spacing) * 3);
791
800
  }
801
+ .-mt-8 {
802
+ margin-top: calc(var(--spacing-8) * -1);
803
+ }
792
804
  .-mt-px {
793
805
  margin-top: -1px;
794
806
  }
@@ -801,6 +813,9 @@
801
813
  .mt-8 {
802
814
  margin-top: var(--spacing-8);
803
815
  }
816
+ .mt-9 {
817
+ margin-top: calc(var(--spacing) * 9);
818
+ }
804
819
  .mt-12 {
805
820
  margin-top: var(--spacing-12);
806
821
  }
@@ -973,6 +988,12 @@
973
988
  .h-\[var\(--cmp-textinput-sm-height\)\] {
974
989
  height: var(--cmp-textinput-sm-height);
975
990
  }
991
+ .h-\[var\(--sys-size-\.\.\.\)\] {
992
+ height: var(--sys-size-...);
993
+ }
994
+ .h-\[var\(--sys-size-control-md-height\)\] {
995
+ height: var(--sys-size-control-md-height);
996
+ }
976
997
  .h-auto {
977
998
  height: auto;
978
999
  }
@@ -1108,6 +1129,9 @@
1108
1129
  .w-\[var\(--cmp-pagination-height\)\] {
1109
1130
  width: var(--cmp-pagination-height);
1110
1131
  }
1132
+ .w-\[var\(--sys-size-control-md-height\)\] {
1133
+ width: var(--sys-size-control-md-height);
1134
+ }
1111
1135
  .w-fit {
1112
1136
  width: fit-content;
1113
1137
  }
@@ -1126,6 +1150,9 @@
1126
1150
  .max-w-\[420px\] {
1127
1151
  max-width: 420px;
1128
1152
  }
1153
+ .max-w-\[1200px\] {
1154
+ max-width: 1200px;
1155
+ }
1129
1156
  .max-w-full {
1130
1157
  max-width: 100%;
1131
1158
  }
@@ -1266,6 +1293,9 @@
1266
1293
  .grid-cols-7 {
1267
1294
  grid-template-columns: repeat(7, minmax(0, 1fr));
1268
1295
  }
1296
+ .grid-cols-\[200px_1fr\] {
1297
+ grid-template-columns: 200px 1fr;
1298
+ }
1269
1299
  .grid-cols-\[repeat\(7\,var\(--cmp-datepicker-calendar-day-width\)\)\] {
1270
1300
  grid-template-columns: repeat(7,var(--cmp-datepicker-calendar-day-width));
1271
1301
  }
@@ -1278,6 +1308,9 @@
1278
1308
  .flex-col {
1279
1309
  flex-direction: column;
1280
1310
  }
1311
+ .flex-col-reverse {
1312
+ flex-direction: column-reverse;
1313
+ }
1281
1314
  .flex-row {
1282
1315
  flex-direction: row;
1283
1316
  }
@@ -1299,6 +1332,9 @@
1299
1332
  .items-stretch {
1300
1333
  align-items: stretch;
1301
1334
  }
1335
+ .justify-around {
1336
+ justify-content: space-around;
1337
+ }
1302
1338
  .justify-between {
1303
1339
  justify-content: space-between;
1304
1340
  }
@@ -1311,6 +1347,9 @@
1311
1347
  .justify-start {
1312
1348
  justify-content: flex-start;
1313
1349
  }
1350
+ .\!gap-12 {
1351
+ gap: var(--spacing-12) !important;
1352
+ }
1314
1353
  .gap-\(--cmp-chipInput-chip-gap\) {
1315
1354
  gap: var(--cmp-chipInput-chip-gap);
1316
1355
  }
@@ -1338,12 +1377,18 @@
1338
1377
  .gap-4 {
1339
1378
  gap: var(--spacing-4);
1340
1379
  }
1380
+ .gap-7 {
1381
+ gap: calc(var(--spacing) * 7);
1382
+ }
1341
1383
  .gap-8 {
1342
1384
  gap: var(--spacing-8);
1343
1385
  }
1344
1386
  .gap-12 {
1345
1387
  gap: var(--spacing-12);
1346
1388
  }
1389
+ .gap-13 {
1390
+ gap: calc(var(--spacing) * 13);
1391
+ }
1347
1392
  .gap-16 {
1348
1393
  gap: var(--spacing-16);
1349
1394
  }
@@ -1365,6 +1410,9 @@
1365
1410
  .gap-\[12px\] {
1366
1411
  gap: 12px;
1367
1412
  }
1413
+ .gap-\[13px\] {
1414
+ gap: 13px;
1415
+ }
1368
1416
  .gap-\[16px\] {
1369
1417
  gap: 16px;
1370
1418
  }
@@ -1377,6 +1425,9 @@
1377
1425
  .gap-\[40px\] {
1378
1426
  gap: 40px;
1379
1427
  }
1428
+ .gap-\[var\(--\.\.\.\)\] {
1429
+ gap: var(--...);
1430
+ }
1380
1431
  .gap-\[var\(--cmp-callout-body-gap\)\] {
1381
1432
  gap: var(--cmp-callout-body-gap);
1382
1433
  }
@@ -1386,6 +1437,9 @@
1386
1437
  .gap-\[var\(--cmp-checkbox-gap\)\] {
1387
1438
  gap: var(--cmp-checkbox-gap);
1388
1439
  }
1440
+ .gap-\[var\(--cmp-checkbox-group-gap-horizontal\)\] {
1441
+ gap: var(--cmp-checkbox-group-gap-horizontal);
1442
+ }
1389
1443
  .gap-\[var\(--cmp-chip-gap\)\] {
1390
1444
  gap: var(--cmp-chip-gap);
1391
1445
  }
@@ -1548,6 +1602,9 @@
1548
1602
  .rounded-\[4px\] {
1549
1603
  border-radius: 4px;
1550
1604
  }
1605
+ .rounded-\[5px\] {
1606
+ border-radius: 5px;
1607
+ }
1551
1608
  .rounded-\[6px\] {
1552
1609
  border-radius: 6px;
1553
1610
  }
@@ -1611,10 +1668,18 @@
1611
1668
  .rounded-none {
1612
1669
  border-radius: 0;
1613
1670
  }
1671
+ .rounded-t {
1672
+ border-top-left-radius: 0.25rem;
1673
+ border-top-right-radius: 0.25rem;
1674
+ }
1614
1675
  .rounded-t-none {
1615
1676
  border-top-left-radius: 0;
1616
1677
  border-top-right-radius: 0;
1617
1678
  }
1679
+ .rounded-l {
1680
+ border-top-left-radius: 0.25rem;
1681
+ border-bottom-left-radius: 0.25rem;
1682
+ }
1618
1683
  .rounded-l-\[4px\] {
1619
1684
  border-top-left-radius: 4px;
1620
1685
  border-bottom-left-radius: 4px;
@@ -1627,6 +1692,13 @@
1627
1692
  border-top-left-radius: var(--cmp-select-sm-radius);
1628
1693
  border-bottom-left-radius: var(--cmp-select-sm-radius);
1629
1694
  }
1695
+ .rounded-tl {
1696
+ border-top-left-radius: 0.25rem;
1697
+ }
1698
+ .rounded-r {
1699
+ border-top-right-radius: 0.25rem;
1700
+ border-bottom-right-radius: 0.25rem;
1701
+ }
1630
1702
  .rounded-r-\[4px\] {
1631
1703
  border-top-right-radius: 4px;
1632
1704
  border-bottom-right-radius: 4px;
@@ -1639,6 +1711,13 @@
1639
1711
  border-top-right-radius: var(--cmp-select-sm-radius);
1640
1712
  border-bottom-right-radius: var(--cmp-select-sm-radius);
1641
1713
  }
1714
+ .rounded-tr {
1715
+ border-top-right-radius: 0.25rem;
1716
+ }
1717
+ .rounded-b {
1718
+ border-bottom-right-radius: 0.25rem;
1719
+ border-bottom-left-radius: 0.25rem;
1720
+ }
1642
1721
  .rounded-b-\[8px\] {
1643
1722
  border-bottom-right-radius: 8px;
1644
1723
  border-bottom-left-radius: 8px;
@@ -1647,6 +1726,12 @@
1647
1726
  border-bottom-right-radius: var(--cmp-table-radius);
1648
1727
  border-bottom-left-radius: var(--cmp-table-radius);
1649
1728
  }
1729
+ .rounded-br {
1730
+ border-bottom-right-radius: 0.25rem;
1731
+ }
1732
+ .rounded-bl {
1733
+ border-bottom-left-radius: 0.25rem;
1734
+ }
1650
1735
  .border {
1651
1736
  border-style: var(--tw-border-style);
1652
1737
  border-width: 1px;
@@ -1799,6 +1884,18 @@
1799
1884
  .border-\[var\(--sys-color-border-default\)\] {
1800
1885
  border-color: var(--sys-color-border-default);
1801
1886
  }
1887
+ .border-border-default {
1888
+ border-color: var(--color-border-default);
1889
+ }
1890
+ .border-border-strong {
1891
+ border-color: var(--color-border-strong);
1892
+ }
1893
+ .border-disabled-border {
1894
+ border-color: var(--color-disabled-border);
1895
+ }
1896
+ .border-divider-default {
1897
+ border-color: var(--color-divider-default);
1898
+ }
1802
1899
  .border-gray-200 {
1803
1900
  border-color: var(--color-gray-200);
1804
1901
  }
@@ -1862,9 +1959,15 @@
1862
1959
  .bg-\(--sys-color-bg-neutralLight\) {
1863
1960
  background-color: var(--sys-color-bg-neutralLight);
1864
1961
  }
1962
+ .bg-\[\#\.\.\.\] {
1963
+ background-color: #...;
1964
+ }
1865
1965
  .bg-\[\#F2F2F2\] {
1866
1966
  background-color: #F2F2F2;
1867
1967
  }
1968
+ .bg-\[\#eee\] {
1969
+ background-color: #eee;
1970
+ }
1868
1971
  .bg-\[var\(--btn-bg\)\] {
1869
1972
  background-color: var(--btn-bg);
1870
1973
  }
@@ -1964,6 +2067,18 @@
1964
2067
  .bg-\[var\(--sys-color-divider-default\)\] {
1965
2068
  background-color: var(--sys-color-divider-default);
1966
2069
  }
2070
+ .bg-bg-frame {
2071
+ background-color: var(--color-bg-frame);
2072
+ }
2073
+ .bg-bg-neutralBright {
2074
+ background-color: var(--color-bg-neutralBright);
2075
+ }
2076
+ .bg-bg-neutralLight {
2077
+ background-color: var(--color-bg-neutralLight);
2078
+ }
2079
+ .bg-bg-screen {
2080
+ background-color: var(--color-bg-screen);
2081
+ }
1967
2082
  .bg-black\/5 {
1968
2083
  background-color: color-mix(in srgb, #000000 5%, transparent);
1969
2084
  @supports (color: color-mix(in lab, red, red)) {
@@ -1976,6 +2091,12 @@
1976
2091
  background-color: color-mix(in oklab, var(--color-black) 40%, transparent);
1977
2092
  }
1978
2093
  }
2094
+ .bg-blue-subtle {
2095
+ background-color: var(--color-blue-subtle);
2096
+ }
2097
+ .bg-disabled-bg {
2098
+ background-color: var(--color-disabled-bg);
2099
+ }
1979
2100
  .bg-gray-200 {
1980
2101
  background-color: var(--color-gray-200);
1981
2102
  }
@@ -2024,6 +2145,12 @@
2024
2145
  .p-12 {
2025
2146
  padding: var(--spacing-12);
2026
2147
  }
2148
+ .p-15 {
2149
+ padding: calc(var(--spacing) * 15);
2150
+ }
2151
+ .p-16 {
2152
+ padding: var(--spacing-16);
2153
+ }
2027
2154
  .p-20 {
2028
2155
  padding: var(--spacing-20);
2029
2156
  }
@@ -2036,6 +2163,9 @@
2036
2163
  .p-\[8px\] {
2037
2164
  padding: 8px;
2038
2165
  }
2166
+ .p-\[10px\] {
2167
+ padding: 10px;
2168
+ }
2039
2169
  .p-\[12px\] {
2040
2170
  padding: 12px;
2041
2171
  }
@@ -2063,6 +2193,9 @@
2063
2193
  .px-8 {
2064
2194
  padding-inline: var(--spacing-8);
2065
2195
  }
2196
+ .px-11 {
2197
+ padding-inline: calc(var(--spacing) * 11);
2198
+ }
2066
2199
  .px-12 {
2067
2200
  padding-inline: var(--spacing-12);
2068
2201
  }
@@ -2304,6 +2437,9 @@
2304
2437
  .text-16 {
2305
2438
  font-size: var(--text-16);
2306
2439
  }
2440
+ .text-18 {
2441
+ font-size: var(--text-18);
2442
+ }
2307
2443
  .text-20 {
2308
2444
  font-size: var(--text-20);
2309
2445
  }
@@ -2383,10 +2519,30 @@
2383
2519
  --tw-leading: 1;
2384
2520
  line-height: 1;
2385
2521
  }
2522
+ .font-\[600\] {
2523
+ --tw-font-weight: 600;
2524
+ font-weight: 600;
2525
+ }
2526
+ .font-black {
2527
+ --tw-font-weight: var(--font-weight-black);
2528
+ font-weight: var(--font-weight-black);
2529
+ }
2386
2530
  .font-bold {
2387
2531
  --tw-font-weight: var(--font-weight-bold);
2388
2532
  font-weight: var(--font-weight-bold);
2389
2533
  }
2534
+ .font-extrabold {
2535
+ --tw-font-weight: var(--font-weight-extrabold);
2536
+ font-weight: var(--font-weight-extrabold);
2537
+ }
2538
+ .font-extralight {
2539
+ --tw-font-weight: var(--font-weight-extralight);
2540
+ font-weight: var(--font-weight-extralight);
2541
+ }
2542
+ .font-light {
2543
+ --tw-font-weight: var(--font-weight-light);
2544
+ font-weight: var(--font-weight-light);
2545
+ }
2390
2546
  .font-medium {
2391
2547
  --tw-font-weight: var(--font-weight-medium);
2392
2548
  font-weight: var(--font-weight-medium);
@@ -2399,6 +2555,10 @@
2399
2555
  --tw-font-weight: var(--font-weight-semibold);
2400
2556
  font-weight: var(--font-weight-semibold);
2401
2557
  }
2558
+ .font-thin {
2559
+ --tw-font-weight: var(--font-weight-thin);
2560
+ font-weight: var(--font-weight-thin);
2561
+ }
2402
2562
  .tracking-wider {
2403
2563
  --tw-tracking: var(--tracking-wider);
2404
2564
  letter-spacing: var(--tracking-wider);
@@ -2487,6 +2647,9 @@
2487
2647
  .text-\[\#0A0A0A\] {
2488
2648
  color: #0A0A0A;
2489
2649
  }
2650
+ .text-\[\#333\] {
2651
+ color: #333;
2652
+ }
2490
2653
  .text-\[\#666\] {
2491
2654
  color: #666;
2492
2655
  }
@@ -2610,6 +2773,30 @@
2610
2773
  .text-blue-strong {
2611
2774
  color: var(--color-blue-strong);
2612
2775
  }
2776
+ .text-fg-accent {
2777
+ color: var(--color-fg-accent);
2778
+ }
2779
+ .text-fg-danger {
2780
+ color: var(--color-fg-danger);
2781
+ }
2782
+ .text-fg-inverse {
2783
+ color: var(--color-fg-inverse);
2784
+ }
2785
+ .text-fg-primary {
2786
+ color: var(--color-fg-primary);
2787
+ }
2788
+ .text-fg-secondary {
2789
+ color: var(--color-fg-secondary);
2790
+ }
2791
+ .text-fg-success {
2792
+ color: var(--color-fg-success);
2793
+ }
2794
+ .text-fg-tertiary {
2795
+ color: var(--color-fg-tertiary);
2796
+ }
2797
+ .text-fg-warning {
2798
+ color: var(--color-fg-warning);
2799
+ }
2613
2800
  .text-gray-400 {
2614
2801
  color: var(--color-gray-400);
2615
2802
  }
@@ -2643,6 +2830,9 @@
2643
2830
  .text-inherit {
2644
2831
  color: inherit;
2645
2832
  }
2833
+ .text-link-accent {
2834
+ color: var(--color-link-accent);
2835
+ }
2646
2836
  .text-red-75 {
2647
2837
  color: var(--color-red-75);
2648
2838
  }
@@ -2711,6 +2901,10 @@
2711
2901
  --tw-shadow: 0px 0px 24px -6px var(--tw-shadow-color, rgba(34,34,34,0.12)), 4px 8px 16px -4px var(--tw-shadow-color, rgba(34,34,34,0.1));
2712
2902
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2713
2903
  }
2904
+ .ring {
2905
+ --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
2906
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2907
+ }
2714
2908
  .outline {
2715
2909
  outline-style: var(--tw-outline-style);
2716
2910
  outline-width: 1px;
@@ -2803,6 +2997,9 @@
2803
2997
  .\[font\:inherit\] {
2804
2998
  font: inherit;
2805
2999
  }
3000
+ .\[length\:var\(--x\)\] {
3001
+ length: var(--x);
3002
+ }
2806
3003
  .group-hover\/filepicker\:text-\[color\:var\(--cmp-filepicker-text-default\)\] {
2807
3004
  &:is(:where(.group\/filepicker):hover *) {
2808
3005
  @media (hover: hover) {
@@ -3051,6 +3248,13 @@
3051
3248
  }
3052
3249
  }
3053
3250
  }
3251
+ .hover\:gap-16 {
3252
+ &:hover {
3253
+ @media (hover: hover) {
3254
+ gap: var(--spacing-16);
3255
+ }
3256
+ }
3257
+ }
3054
3258
  .hover\:\!border-\[color\:var\(--cmp-radioButton-bg-hover\)\] {
3055
3259
  &:hover {
3056
3260
  @media (hover: hover) {
@@ -3551,6 +3755,20 @@
3551
3755
  transition-property: none;
3552
3756
  }
3553
3757
  }
3758
+ .md\:px-24 {
3759
+ @media (width >= 48rem) {
3760
+ padding-inline: var(--spacing-24);
3761
+ }
3762
+ }
3763
+ .hover\:md\:gap-12 {
3764
+ &:hover {
3765
+ @media (hover: hover) {
3766
+ @media (width >= 48rem) {
3767
+ gap: var(--spacing-12);
3768
+ }
3769
+ }
3770
+ }
3771
+ }
3554
3772
  .\[\&\:\:-webkit-scrollbar\]\:hidden {
3555
3773
  &::-webkit-scrollbar {
3556
3774
  display: none;
@@ -4713,6 +4931,9 @@
4713
4931
  --cmp-tree-connector-line-color: #AAAAAA;
4714
4932
  }
4715
4933
  @layer base {
4934
+ body {
4935
+ color: var(--color-fg-primary);
4936
+ }
4716
4937
  *::-webkit-scrollbar {
4717
4938
  width: 12px;
4718
4939
  height: 12px;
package/dist/theme.css CHANGED
@@ -1439,6 +1439,14 @@
1439
1439
  Chrome 121+/WebKit 는 scrollbar-width·scrollbar-color 계산값이 auto 가 아니면 ::-webkit-scrollbar-* 를 통째로
1440
1440
  무시하므로, 표준 속성은 webkit 유사요소가 없는 브라우저(Firefox)에서만 켠다. */
1441
1441
  @layer base {
1442
+ /* 전역 기본 텍스트 색 — 본문은 grey_95(= fg.primary). 요소마다 색을 지정하지 않아도
1443
+ 브라우저 기본 검정(#000)이 아니라 디자인 시스템 색으로 렌더된다.
1444
+ 보조·비활성 텍스트만 text-fg-tertiary(grey_65)로 내려 쓴다.
1445
+ base 레이어라 소비 앱의 text-* 유틸리티(utilities)가 언제든 덮어쓴다. */
1446
+ body {
1447
+ color: var(--color-fg-primary);
1448
+ }
1449
+
1442
1450
  *::-webkit-scrollbar {
1443
1451
  width: 12px;
1444
1452
  height: 12px;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * sellmate-design-system-react — 소비 앱용 ESLint 플러그인.
3
+ *
4
+ * AGENTS.md 의 규칙 중 정적으로 검출 가능한 것을 린트로 강제한다.
5
+ * 사용법은 README 의 "ESLint 설정" 절 참조.
6
+ */
7
+ import noRawHtmlControl from "./rules/no-raw-html-control.mjs";
8
+ import noArbitraryClass from "./rules/no-arbitrary-class.mjs";
9
+ import noOffScaleSpacing from "./rules/no-off-scale-spacing.mjs";
10
+ import preferTypoPreset from "./rules/prefer-typo-preset.mjs";
11
+ import tableNumericAlign from "./rules/table-numeric-align.mjs";
12
+ import requireLocaleNumber from "./rules/require-locale-number.mjs";
13
+ import componentGroupGap from "./rules/component-group-gap.mjs";
14
+
15
+ const PLUGIN_NAME = "sellmate";
16
+
17
+ const plugin = {
18
+ meta: { name: "eslint-plugin-sellmate" },
19
+ rules: {
20
+ "no-raw-html-control": noRawHtmlControl,
21
+ "no-arbitrary-class": noArbitraryClass,
22
+ "no-off-scale-spacing": noOffScaleSpacing,
23
+ "prefer-typo-preset": preferTypoPreset,
24
+ "table-numeric-align": tableNumericAlign,
25
+ "require-locale-number": requireLocaleNumber,
26
+ "component-group-gap": componentGroupGap,
27
+ },
28
+ };
29
+
30
+ /** 기본 프리셋 — JSX/TSX 파일에 적용 */
31
+ const recommended = [
32
+ {
33
+ // 컬럼 정의를 .ts 파일로 분리하는 경우가 있어 tsx 뿐 아니라 ts 도 포함한다
34
+ files: ["**/*.{js,jsx,ts,tsx}"],
35
+ plugins: { [PLUGIN_NAME]: plugin },
36
+ rules: {
37
+ // 스타일이 조용히 사라지거나 디자인 시스템을 우회하는 경우 → error
38
+ [`${PLUGIN_NAME}/no-raw-html-control`]: "error",
39
+ [`${PLUGIN_NAME}/no-arbitrary-class`]: "error",
40
+ [`${PLUGIN_NAME}/no-off-scale-spacing`]: "error",
41
+ [`${PLUGIN_NAME}/table-numeric-align`]: "error",
42
+ [`${PLUGIN_NAME}/require-locale-number`]: "error",
43
+ [`${PLUGIN_NAME}/component-group-gap`]: "error",
44
+ // 대체 프리셋 판단에 여지가 있어 warn
45
+ [`${PLUGIN_NAME}/prefer-typo-preset`]: "warn",
46
+ },
47
+ },
48
+ ];
49
+
50
+ /**
51
+ * 전 규칙 error + ul·ol·li·svg·label 까지 검사.
52
+ * 정당한 사용처(로고 SVG, 시맨틱 목록 등)가 있는 요소도 잡히므로
53
+ * 예외는 `allow` 로 열어 쓰는 것을 전제로 한다. 신규 프로젝트용.
54
+ */
55
+ const strict = [
56
+ {
57
+ ...recommended[0],
58
+ rules: {
59
+ ...recommended[0].rules,
60
+ [`${PLUGIN_NAME}/no-raw-html-control`]: ["error", { strict: true }],
61
+ [`${PLUGIN_NAME}/prefer-typo-preset`]: "error",
62
+ },
63
+ },
64
+ ];
65
+
66
+ plugin.configs = { recommended, strict };
67
+
68
+ export default plugin;
69
+ export const { rules, configs } = plugin;
@@ -0,0 +1,119 @@
1
+ /**
2
+ * className / class 속성에서 클래스 토큰을 추출하는 공용 헬퍼.
3
+ *
4
+ * 지원 형태:
5
+ * className="a b" → Literal
6
+ * className={`a ${x} b`} → TemplateLiteral (정적 quasi 부분만)
7
+ * className={cn('a', cond && 'b')} → clsx/cn/classnames 호출의 문자열 인자
8
+ * className={'a b'} → JSXExpressionContainer > Literal
9
+ *
10
+ * 동적으로 조립되는 부분(변수·삼항의 식별자 등)은 정적 분석 대상이 아니므로 건너뛴다.
11
+ */
12
+
13
+ const CLASS_ATTRS = new Set(["className", "class"]);
14
+ const CLASS_HELPERS = new Set(["cn", "clsx", "classNames", "classnames", "cva", "twMerge"]);
15
+
16
+ /** 문자열을 공백 기준 클래스 토큰으로 나눈다 (variant 접두어는 유지) */
17
+ export function tokenize(value) {
18
+ return String(value)
19
+ .split(/\s+/)
20
+ .filter(Boolean);
21
+ }
22
+
23
+ /**
24
+ * `hover:md:gap-12` → `gap-12` — variant 접두어를 벗겨 유틸리티 본체만 남긴다.
25
+ * 임의 값 안의 `:`(예: `[length:var(--x)]`)는 벗기지 않는다.
26
+ */
27
+ export function stripVariants(token) {
28
+ let rest = token;
29
+ for (;;) {
30
+ const idx = indexOfTopLevelColon(rest);
31
+ if (idx === -1) return rest;
32
+ rest = rest.slice(idx + 1);
33
+ }
34
+ }
35
+
36
+ /** 대괄호 밖에 있는 첫 `:` 위치 (없으면 -1) */
37
+ function indexOfTopLevelColon(s) {
38
+ let depth = 0;
39
+ for (let i = 0; i < s.length; i++) {
40
+ const c = s[i];
41
+ if (c === "[") depth++;
42
+ else if (c === "]") depth--;
43
+ else if (c === ":" && depth === 0) return i;
44
+ }
45
+ return -1;
46
+ }
47
+
48
+ /** `!gap-12` / `-mt-8` 같은 접두 기호 제거 */
49
+ export function stripModifiers(token) {
50
+ return token.replace(/^!/, "").replace(/^-/, "");
51
+ }
52
+
53
+ /**
54
+ * JSXAttribute 노드에서 정적으로 알 수 있는 클래스 토큰을 모두 수집한다.
55
+ * @returns {Array<{ token: string, node: import('estree').Node }>}
56
+ */
57
+ export function collectClassTokens(attrNode) {
58
+ if (attrNode.type !== "JSXAttribute") return [];
59
+ const name = attrNode.name?.name;
60
+ if (!CLASS_ATTRS.has(name)) return [];
61
+
62
+ const out = [];
63
+ const push = (raw, node) => {
64
+ for (const token of tokenize(raw)) out.push({ token, node });
65
+ };
66
+
67
+ const visit = (node) => {
68
+ if (!node) return;
69
+ switch (node.type) {
70
+ case "Literal":
71
+ if (typeof node.value === "string") push(node.value, node);
72
+ break;
73
+ case "TemplateLiteral":
74
+ // 정적 부분만 본다. 보간(${}) 안쪽은 아래 표현식 방문으로 따로 처리.
75
+ for (const q of node.quasis) push(q.value.cooked ?? "", node);
76
+ for (const e of node.expressions) visit(e);
77
+ break;
78
+ case "JSXExpressionContainer":
79
+ visit(node.expression);
80
+ break;
81
+ case "CallExpression": {
82
+ const callee = node.callee;
83
+ const fnName = callee?.type === "Identifier" ? callee.name : callee?.property?.name;
84
+ if (fnName && CLASS_HELPERS.has(fnName)) {
85
+ for (const arg of node.arguments) visit(arg);
86
+ }
87
+ break;
88
+ }
89
+ case "ConditionalExpression":
90
+ visit(node.consequent);
91
+ visit(node.alternate);
92
+ break;
93
+ case "LogicalExpression":
94
+ visit(node.left);
95
+ visit(node.right);
96
+ break;
97
+ case "ArrayExpression":
98
+ for (const el of node.elements) visit(el);
99
+ break;
100
+ case "ObjectExpression":
101
+ // clsx({ 'gap-12': cond }) 형태 — 키가 클래스다
102
+ for (const prop of node.properties) {
103
+ if (prop.type === "Property" && prop.key) {
104
+ if (prop.key.type === "Literal" && typeof prop.key.value === "string") {
105
+ push(prop.key.value, prop.key);
106
+ } else if (prop.key.type === "Identifier" && !prop.computed) {
107
+ push(prop.key.name, prop.key);
108
+ }
109
+ }
110
+ }
111
+ break;
112
+ default:
113
+ break;
114
+ }
115
+ };
116
+
117
+ visit(attrNode.value);
118
+ return out;
119
+ }