sellmate-design-system-react 9.0.0-beta.21 → 9.0.0-beta.24

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.
package/dist/styles.css CHANGED
@@ -755,18 +755,24 @@
755
755
  .mx-3 {
756
756
  margin-inline: calc(var(--spacing) * 3);
757
757
  }
758
- .mx-\[2px\] {
759
- margin-inline: 2px;
758
+ .mx-\[4px\] {
759
+ margin-inline: 4px;
760
760
  }
761
761
  .mx-\[calc\(12px-var\(--cmp-chipFilter-chip-group\)\)\] {
762
762
  margin-inline: calc(12px - var(--cmp-chipFilter-chip-group));
763
763
  }
764
+ .my-\[4px\] {
765
+ margin-block: 4px;
766
+ }
764
767
  .my-\[6px\] {
765
768
  margin-block: 6px;
766
769
  }
767
770
  .my-auto {
768
771
  margin-block: auto;
769
772
  }
773
+ .my-sd-8 {
774
+ margin-block: var(--spacing-sd-8);
775
+ }
770
776
  .-mt-8 {
771
777
  margin-top: calc(var(--spacing) * -8);
772
778
  }
@@ -794,6 +800,9 @@
794
800
  .mt-\[2px\] {
795
801
  margin-top: 2px;
796
802
  }
803
+ .mt-\[6px\] {
804
+ margin-top: 6px;
805
+ }
797
806
  .mt-\[8px\] {
798
807
  margin-top: 8px;
799
808
  }
@@ -803,6 +812,9 @@
803
812
  .mt-\[var\(--cmp-guide-contents-gap\)\] {
804
813
  margin-top: var(--cmp-guide-contents-gap);
805
814
  }
815
+ .mt-auto {
816
+ margin-top: auto;
817
+ }
806
818
  .mt-sd-2 {
807
819
  margin-top: var(--spacing-sd-2);
808
820
  }
@@ -839,6 +851,9 @@
839
851
  .mb-\[24px\] {
840
852
  margin-bottom: 24px;
841
853
  }
854
+ .mb-auto {
855
+ margin-bottom: auto;
856
+ }
842
857
  .mb-sd-8 {
843
858
  margin-bottom: var(--spacing-sd-8);
844
859
  }
@@ -924,6 +939,9 @@
924
939
  .h-48 {
925
940
  height: calc(var(--spacing) * 48);
926
941
  }
942
+ .h-\[1px\] {
943
+ height: 1px;
944
+ }
927
945
  .h-\[2px\] {
928
946
  height: 2px;
929
947
  }
@@ -1020,9 +1038,6 @@
1020
1038
  .h-\[var\(--cmp-datepicker-calendar-day-dot-size\)\] {
1021
1039
  height: var(--cmp-datepicker-calendar-day-dot-size);
1022
1040
  }
1023
- .h-\[var\(--cmp-datepicker-calendar-header-divider-height\)\] {
1024
- height: var(--cmp-datepicker-calendar-header-divider-height);
1025
- }
1026
1041
  .h-\[var\(--cmp-datepicker-calendar-range-height\)\] {
1027
1042
  height: var(--cmp-datepicker-calendar-range-height);
1028
1043
  }
@@ -1053,6 +1068,9 @@
1053
1068
  .h-\[var\(--sys-size-control-md-height\)\] {
1054
1069
  height: var(--sys-size-control-md-height);
1055
1070
  }
1071
+ .h-\[var\(--x\)\] {
1072
+ height: var(--x);
1073
+ }
1056
1074
  .h-auto {
1057
1075
  height: auto;
1058
1076
  }
@@ -1071,6 +1089,9 @@
1071
1089
  .h-sd-8 {
1072
1090
  height: var(--spacing-sd-8);
1073
1091
  }
1092
+ .h-sd-20 {
1093
+ height: var(--spacing-sd-20);
1094
+ }
1074
1095
  .h-sd-32 {
1075
1096
  height: var(--spacing-sd-32);
1076
1097
  }
@@ -1329,6 +1350,9 @@
1329
1350
  .min-w-\[40px\] {
1330
1351
  min-width: 40px;
1331
1352
  }
1353
+ .min-w-\[72px\] {
1354
+ min-width: 72px;
1355
+ }
1332
1356
  .min-w-\[160px\] {
1333
1357
  min-width: 160px;
1334
1358
  }
@@ -1831,6 +1855,9 @@
1831
1855
  .overflow-auto {
1832
1856
  overflow: auto;
1833
1857
  }
1858
+ .overflow-clip {
1859
+ overflow: clip;
1860
+ }
1834
1861
  .overflow-hidden {
1835
1862
  overflow: hidden;
1836
1863
  }
@@ -2380,6 +2407,9 @@
2380
2407
  .bg-\[var\(--cmp-listBoxItem-depth2-middle-bg\)\] {
2381
2408
  background-color: var(--cmp-listBoxItem-depth2-middle-bg);
2382
2409
  }
2410
+ .bg-\[var\(--cmp-listItem-bg-selected\)\] {
2411
+ background-color: var(--cmp-listItem-bg-selected);
2412
+ }
2383
2413
  .bg-\[var\(--cmp-modal-bg\)\] {
2384
2414
  background-color: var(--cmp-modal-bg);
2385
2415
  }
@@ -2434,6 +2464,9 @@
2434
2464
  .bg-\[var\(--sys-color-bg-screen\)\] {
2435
2465
  background-color: var(--sys-color-bg-screen);
2436
2466
  }
2467
+ .bg-\[var\(--sys-color-border-default\)\] {
2468
+ background-color: var(--sys-color-border-default);
2469
+ }
2437
2470
  .bg-\[var\(--sys-color-divider-default\)\] {
2438
2471
  background-color: var(--sys-color-divider-default);
2439
2472
  }
@@ -2494,6 +2527,9 @@
2494
2527
  .bg-grey-90 {
2495
2528
  background-color: var(--color-grey-90);
2496
2529
  }
2530
+ .bg-inherit {
2531
+ background-color: inherit;
2532
+ }
2497
2533
  .bg-primary-50 {
2498
2534
  background-color: var(--color-primary-50);
2499
2535
  }
@@ -3255,6 +3291,9 @@
3255
3291
  .text-\[color\:var\(--cmp-listBoxItem-content-selected\)\] {
3256
3292
  color: var(--cmp-listBoxItem-content-selected);
3257
3293
  }
3294
+ .text-\[color\:var\(--cmp-listItem-text-selected\)\] {
3295
+ color: var(--cmp-listItem-text-selected);
3296
+ }
3258
3297
  .text-\[color\:var\(--cmp-modal-confirm-message-color\)\] {
3259
3298
  color: var(--cmp-modal-confirm-message-color);
3260
3299
  }
@@ -4301,11 +4340,21 @@
4301
4340
  cursor: not-allowed;
4302
4341
  }
4303
4342
  }
4343
+ .data-\[disabled\]\:bg-transparent {
4344
+ &[data-disabled] {
4345
+ background-color: transparent;
4346
+ }
4347
+ }
4304
4348
  .data-\[disabled\]\:text-\[color\:var\(--cmp-button-text-disabled\)\] {
4305
4349
  &[data-disabled] {
4306
4350
  color: var(--cmp-button-text-disabled);
4307
4351
  }
4308
4352
  }
4353
+ .data-\[disabled\]\:text-\[color\:var\(--cmp-ghostButton-icon-disabled\)\] {
4354
+ &[data-disabled] {
4355
+ color: var(--cmp-ghostButton-icon-disabled);
4356
+ }
4357
+ }
4309
4358
  .data-\[highlighted\]\:bg-\[var\(--color-bg-neutralLight\)\] {
4310
4359
  &[data-highlighted] {
4311
4360
  background-color: var(--color-bg-neutralLight);
@@ -4496,6 +4545,11 @@
4496
4545
  transition-property: none;
4497
4546
  }
4498
4547
  }
4548
+ .md\:h-sd-20 {
4549
+ @media (width >= 48rem) {
4550
+ height: var(--spacing-sd-20);
4551
+ }
4552
+ }
4499
4553
  .md\:p-4 {
4500
4554
  @media (width >= 48rem) {
4501
4555
  padding: calc(var(--spacing) * 4);
@@ -4558,6 +4612,264 @@
4558
4612
  outline-color: var(--color-border-accent);
4559
4613
  }
4560
4614
  }
4615
+ .\[\&_\.sd-editor-image\]\:my-\[8px\] {
4616
+ & .sd-editor-image {
4617
+ margin-block: 8px;
4618
+ }
4619
+ }
4620
+ .\[\&_\.sd-editor-image\]\:h-auto {
4621
+ & .sd-editor-image {
4622
+ height: auto;
4623
+ }
4624
+ }
4625
+ .\[\&_\.sd-editor-image\]\:max-w-full {
4626
+ & .sd-editor-image {
4627
+ max-width: 100%;
4628
+ }
4629
+ }
4630
+ .\[\&_\.sd-editor-image\]\:rounded-\[4px\] {
4631
+ & .sd-editor-image {
4632
+ border-radius: 4px;
4633
+ }
4634
+ }
4635
+ .\[\&_\.sd-editor-table\]\:my-\[8px\] {
4636
+ & .sd-editor-table {
4637
+ margin-block: 8px;
4638
+ }
4639
+ }
4640
+ .\[\&_\.sd-editor-table\]\:w-full {
4641
+ & .sd-editor-table {
4642
+ width: 100%;
4643
+ }
4644
+ }
4645
+ .\[\&_\.sd-editor-table\]\:table-fixed {
4646
+ & .sd-editor-table {
4647
+ table-layout: fixed;
4648
+ }
4649
+ }
4650
+ .\[\&_\.sd-editor-table\]\:border-collapse {
4651
+ & .sd-editor-table {
4652
+ border-collapse: collapse;
4653
+ }
4654
+ }
4655
+ .\[\&_\.sd-editor-table-cell\]\:border {
4656
+ & .sd-editor-table-cell {
4657
+ border-style: var(--tw-border-style);
4658
+ border-width: 1px;
4659
+ }
4660
+ }
4661
+ .\[\&_\.sd-editor-table-cell\]\:border-solid {
4662
+ & .sd-editor-table-cell {
4663
+ --tw-border-style: solid;
4664
+ border-style: solid;
4665
+ }
4666
+ }
4667
+ .\[\&_\.sd-editor-table-cell\]\:border-\[color\:var\(--color-border-default\)\] {
4668
+ & .sd-editor-table-cell {
4669
+ border-color: var(--color-border-default);
4670
+ }
4671
+ }
4672
+ .\[\&_\.sd-editor-table-cell\]\:px-\[8px\] {
4673
+ & .sd-editor-table-cell {
4674
+ padding-inline: 8px;
4675
+ }
4676
+ }
4677
+ .\[\&_\.sd-editor-table-cell\]\:py-\[4px\] {
4678
+ & .sd-editor-table-cell {
4679
+ padding-block: 4px;
4680
+ }
4681
+ }
4682
+ .\[\&_\.sd-editor-table-cell\]\:align-top {
4683
+ & .sd-editor-table-cell {
4684
+ vertical-align: top;
4685
+ }
4686
+ }
4687
+ .\[\&_\.sd-editor-table-cell\>p\]\:my-0 {
4688
+ & .sd-editor-table-cell>p {
4689
+ margin-block: 0;
4690
+ }
4691
+ }
4692
+ .\[\&_\.sd-editor-table-header\]\:border {
4693
+ & .sd-editor-table-header {
4694
+ border-style: var(--tw-border-style);
4695
+ border-width: 1px;
4696
+ }
4697
+ }
4698
+ .\[\&_\.sd-editor-table-header\]\:border-solid {
4699
+ & .sd-editor-table-header {
4700
+ --tw-border-style: solid;
4701
+ border-style: solid;
4702
+ }
4703
+ }
4704
+ .\[\&_\.sd-editor-table-header\]\:border-\[color\:var\(--color-border-default\)\] {
4705
+ & .sd-editor-table-header {
4706
+ border-color: var(--color-border-default);
4707
+ }
4708
+ }
4709
+ .\[\&_\.sd-editor-table-header\]\:bg-\[var\(--color-bg-neutralLight\)\] {
4710
+ & .sd-editor-table-header {
4711
+ background-color: var(--color-bg-neutralLight);
4712
+ }
4713
+ }
4714
+ .\[\&_\.sd-editor-table-header\]\:px-\[8px\] {
4715
+ & .sd-editor-table-header {
4716
+ padding-inline: 8px;
4717
+ }
4718
+ }
4719
+ .\[\&_\.sd-editor-table-header\]\:py-\[4px\] {
4720
+ & .sd-editor-table-header {
4721
+ padding-block: 4px;
4722
+ }
4723
+ }
4724
+ .\[\&_\.sd-editor-table-header\]\:text-left {
4725
+ & .sd-editor-table-header {
4726
+ text-align: left;
4727
+ }
4728
+ }
4729
+ .\[\&_\.sd-editor-table-header\]\:align-top {
4730
+ & .sd-editor-table-header {
4731
+ vertical-align: top;
4732
+ }
4733
+ }
4734
+ .\[\&_\.sd-editor-table-header\]\:font-bold {
4735
+ & .sd-editor-table-header {
4736
+ --tw-font-weight: var(--font-weight-bold);
4737
+ font-weight: var(--font-weight-bold);
4738
+ }
4739
+ }
4740
+ .\[\&_\.sd-editor-table-header\>p\]\:my-0 {
4741
+ & .sd-editor-table-header>p {
4742
+ margin-block: 0;
4743
+ }
4744
+ }
4745
+ .\[\&_\.sd-editor-task-item\]\:flex {
4746
+ & .sd-editor-task-item {
4747
+ display: flex;
4748
+ }
4749
+ }
4750
+ .\[\&_\.sd-editor-task-item\]\:items-start {
4751
+ & .sd-editor-task-item {
4752
+ align-items: flex-start;
4753
+ }
4754
+ }
4755
+ .\[\&_\.sd-editor-task-item\]\:gap-\[6px\] {
4756
+ & .sd-editor-task-item {
4757
+ gap: 6px;
4758
+ }
4759
+ }
4760
+ .\[\&_\.sd-editor-task-item_input\]\:m-0 {
4761
+ & .sd-editor-task-item input {
4762
+ margin: 0;
4763
+ }
4764
+ }
4765
+ .\[\&_\.sd-editor-task-item_input\]\:h-\[13px\] {
4766
+ & .sd-editor-task-item input {
4767
+ height: 13px;
4768
+ }
4769
+ }
4770
+ .\[\&_\.sd-editor-task-item_input\]\:w-\[13px\] {
4771
+ & .sd-editor-task-item input {
4772
+ width: 13px;
4773
+ }
4774
+ }
4775
+ .\[\&_\.sd-editor-task-item_input\]\:cursor-pointer {
4776
+ & .sd-editor-task-item input {
4777
+ cursor: pointer;
4778
+ }
4779
+ }
4780
+ .\[\&_\.sd-editor-task-item_input\]\:accent-\[var\(--color-fg-accent\)\] {
4781
+ & .sd-editor-task-item input {
4782
+ accent-color: var(--color-fg-accent);
4783
+ }
4784
+ }
4785
+ .\[\&_\.sd-editor-task-item\>div\]\:min-w-0 {
4786
+ & .sd-editor-task-item>div {
4787
+ min-width: 0;
4788
+ }
4789
+ }
4790
+ .\[\&_\.sd-editor-task-item\>div\]\:flex-1 {
4791
+ & .sd-editor-task-item>div {
4792
+ flex: 1;
4793
+ }
4794
+ }
4795
+ .\[\&_\.sd-editor-task-item\>label\]\:mt-\[3px\] {
4796
+ & .sd-editor-task-item>label {
4797
+ margin-top: 3px;
4798
+ }
4799
+ }
4800
+ .\[\&_\.sd-editor-task-item\>label\]\:shrink-0 {
4801
+ & .sd-editor-task-item>label {
4802
+ flex-shrink: 0;
4803
+ }
4804
+ }
4805
+ .\[\&_\.sd-editor-task-item\>label\]\:leading-none {
4806
+ & .sd-editor-task-item>label {
4807
+ --tw-leading: 1;
4808
+ line-height: 1;
4809
+ }
4810
+ }
4811
+ .\[\&_\.sd-editor-task-item\[data-checked\=true\]\>div\]\:text-\[color\:var\(--color-fg-tertiary\)\] {
4812
+ & .sd-editor-task-item[data-checked=true]>div {
4813
+ color: var(--color-fg-tertiary);
4814
+ }
4815
+ }
4816
+ .\[\&_\.sd-editor-task-item\[data-checked\=true\]\>div\]\:line-through {
4817
+ & .sd-editor-task-item[data-checked=true]>div {
4818
+ text-decoration-line: line-through;
4819
+ }
4820
+ }
4821
+ .\[\&_\.sd-editor-task-list\]\:my-\[4px\] {
4822
+ & .sd-editor-task-list {
4823
+ margin-block: 4px;
4824
+ }
4825
+ }
4826
+ .\[\&_\.sd-editor-task-list\]\:list-none {
4827
+ & .sd-editor-task-list {
4828
+ list-style-type: none;
4829
+ }
4830
+ }
4831
+ .\[\&_\.sd-editor-task-list\]\:pl-0 {
4832
+ & .sd-editor-task-list {
4833
+ padding-left: 0;
4834
+ }
4835
+ }
4836
+ .\[\&_\.selectedCell\]\:relative {
4837
+ & .selectedCell {
4838
+ position: relative;
4839
+ }
4840
+ }
4841
+ .\[\&_\.selectedCell\]\:after\:pointer-events-none {
4842
+ & .selectedCell {
4843
+ &::after {
4844
+ content: var(--tw-content);
4845
+ pointer-events: none;
4846
+ }
4847
+ }
4848
+ }
4849
+ .\[\&_\.selectedCell\]\:after\:absolute {
4850
+ & .selectedCell {
4851
+ &::after {
4852
+ content: var(--tw-content);
4853
+ position: absolute;
4854
+ }
4855
+ }
4856
+ }
4857
+ .\[\&_\.selectedCell\]\:after\:inset-0 {
4858
+ & .selectedCell {
4859
+ &::after {
4860
+ content: var(--tw-content);
4861
+ inset: 0;
4862
+ }
4863
+ }
4864
+ }
4865
+ .\[\&_\.selectedCell\]\:after\:bg-\[var\(--color-bg-accentFaint\)\] {
4866
+ & .selectedCell {
4867
+ &::after {
4868
+ content: var(--tw-content);
4869
+ background-color: var(--color-bg-accentFaint);
4870
+ }
4871
+ }
4872
+ }
4561
4873
  .\[\&_a\]\:cursor-pointer {
4562
4874
  & a {
4563
4875
  cursor: pointer;
@@ -4737,21 +5049,6 @@
4737
5049
  margin-block: 0;
4738
5050
  }
4739
5051
  }
4740
- .\[\&_mark\]\:rounded-\[2px\] {
4741
- & mark {
4742
- border-radius: 2px;
4743
- }
4744
- }
4745
- .\[\&_mark\]\:bg-transparent {
4746
- & mark {
4747
- background-color: transparent;
4748
- }
4749
- }
4750
- .\[\&_mark\]\:px-\[1px\] {
4751
- & mark {
4752
- padding-inline: 1px;
4753
- }
4754
- }
4755
5052
  .\[\&_ol\]\:my-\[4px\] {
4756
5053
  & ol {
4757
5054
  margin-block: 4px;
@@ -4858,26 +5155,6 @@
4858
5155
  font-weight: var(--font-weight-bold);
4859
5156
  }
4860
5157
  }
4861
- .\[\&_sub\]\:align-sub {
4862
- & sub {
4863
- vertical-align: sub;
4864
- }
4865
- }
4866
- .\[\&_sub\]\:text-\[0\.75em\] {
4867
- & sub {
4868
- font-size: 0.75em;
4869
- }
4870
- }
4871
- .\[\&_sup\]\:align-super {
4872
- & sup {
4873
- vertical-align: super;
4874
- }
4875
- }
4876
- .\[\&_sup\]\:text-\[0\.75em\] {
4877
- & sup {
4878
- font-size: 0.75em;
4879
- }
4880
- }
4881
5158
  .\[\&_u\]\:underline {
4882
5159
  & u {
4883
5160
  text-decoration-line: underline;
package/eslint/index.mjs CHANGED
@@ -13,6 +13,7 @@ import requireLocaleNumber from "./rules/require-locale-number.mjs";
13
13
  import componentGroupGap from "./rules/component-group-gap.mjs";
14
14
  import fieldWidthGrade from "./rules/field-width-grade.mjs";
15
15
  import tableColumnWidth from "./rules/table-column-width.mjs";
16
+ import dividerVerticalHeight from "./rules/divider-vertical-height.mjs";
16
17
 
17
18
  const PLUGIN_NAME = "sellmate";
18
19
 
@@ -28,6 +29,7 @@ const plugin = {
28
29
  "component-group-gap": componentGroupGap,
29
30
  "field-width-grade": fieldWidthGrade,
30
31
  "table-column-width": tableColumnWidth,
32
+ "divider-vertical-height": dividerVerticalHeight,
31
33
  },
32
34
  };
33
35
 
@@ -52,6 +54,8 @@ const recommended = [
52
54
  [`${PLUGIN_NAME}/no-off-scale-spacing`]: "error",
53
55
  // 생 <button>/<table> 은 디자인 시스템을 통째로 우회하는 것 (스타일 자유와 무관)
54
56
  [`${PLUGIN_NAME}/no-raw-html-control`]: "error",
57
+ // 세로 SDivider 에 className 으로 높이를 주면 self-stretch 가 무효가 되어 선이 위로 솟는다
58
+ [`${PLUGIN_NAME}/divider-vertical-height`]: "error",
55
59
 
56
60
  // 아래는 디자인 컨벤션 — 권고만 한다
57
61
  [`${PLUGIN_NAME}/prefer-typo-preset`]: "warn",
@@ -0,0 +1,137 @@
1
+ /**
2
+ * 세로 `SDivider` 의 높이를 `className="h-*"` 로 주면 정렬이 조용히 깨지는 것을 잡는다.
3
+ *
4
+ * 세로 분할선의 기본값은 `h-auto ... self-stretch` 라, 높이를 주지 않으면 부모 줄 높이를
5
+ * 그대로 채운다. 그런데 `align-self: stretch` 는 **교차축 크기가 auto 일 때만** 늘리므로
6
+ * className 으로 높이가 정해지는 순간 stretch 가 무효가 되고 flex-start 처럼 줄 맨 위에
7
+ * 붙는다. tailwind-merge 는 `h-auto` 만 교체하고 `self-stretch` 는 남기므로 경고도 없다.
8
+ *
9
+ * 높이와 정렬은 같이 정해져야 하는 값이라 컴포넌트가 함께 맡는다 — `height` prop 을 쓴다.
10
+ *
11
+ * <SDivider vertical height={20} /> // 높이 + self-center
12
+ * <SDivider vertical className="h-sd-20" /> // 위로 솟는다
13
+ *
14
+ * 정렬을 **직접 지정한 경우**(`self-center` `self-start` `my-auto` …)는 알고 쓰는 것으로
15
+ * 보고 잡지 않는다.
16
+ *
17
+ * AGENTS.md §3-6.
18
+ */
19
+ import { collectClassTokens, stripVariants, stripModifiers } from "../lib/class-names.mjs";
20
+
21
+ /** 높이를 정하는 유틸리티인가 — `h-auto` 만 예외(기본값과 같아 stretch 가 살아 있다) */
22
+ function heightUtil(util) {
23
+ const m = /^h-(.+)$/.exec(util);
24
+ if (!m || m[1] === "auto") return null;
25
+ return m[1];
26
+ }
27
+
28
+ /** 교차축 정렬을 이미 직접 지정했는가 */
29
+ function alignsSelf(util) {
30
+ return /^self-/.test(util) || util === "my-auto" || util === "mt-auto" || util === "mb-auto";
31
+ }
32
+
33
+ /**
34
+ * 높이 유틸리티 값을 `height` prop 값으로 옮긴다. 옮길 수 없으면 null (수정 제안 없음).
35
+ * h-sd-20 → {20}
36
+ * h-[20px] → {20}
37
+ * h-[var(--x)] → "var(--x)"
38
+ */
39
+ function toHeightProp(value) {
40
+ const scaled = /^sd-(\d+)$/.exec(value);
41
+ if (scaled) return `{${scaled[1]}}`;
42
+ const arbitrary = /^\[(.+)\]$/.exec(value);
43
+ if (!arbitrary) return null;
44
+ const inner = arbitrary[1].replace(/_/g, " ");
45
+ const px = /^(\d+(?:\.\d+)?)px$/.exec(inner);
46
+ if (px) return `{${px[1]}}`;
47
+ if (inner.includes('"')) return null;
48
+ return `"${inner}"`;
49
+ }
50
+
51
+ const isClassAttr = (a) =>
52
+ a.type === "JSXAttribute" && (a.name?.name === "className" || a.name?.name === "class");
53
+
54
+ export default {
55
+ meta: {
56
+ type: "problem",
57
+ docs: {
58
+ description: "세로 SDivider 의 높이는 className 이 아니라 height prop 으로 지정",
59
+ },
60
+ schema: [],
61
+ messages: {
62
+ useHeightProp:
63
+ "세로 SDivider 의 높이는 `height` prop 으로 주세요{{suggestion}} — `className` 으로 주면 `align-self: stretch` 가 무효가 되어 선이 줄 맨 위에 붙습니다. (AGENTS.md §3-6)",
64
+ },
65
+ fixable: "code",
66
+ },
67
+
68
+ create(context) {
69
+ return {
70
+ JSXOpeningElement(node) {
71
+ if (node.name.type !== "JSXIdentifier" || node.name.name !== "SDivider") return;
72
+
73
+ const attrs = node.attributes;
74
+ const named = (n) => attrs.find((a) => a.type === "JSXAttribute" && a.name?.name === n);
75
+
76
+ // 세로 분할선만 대상. `vertical={expr}` 처럼 값이 정적이지 않으면 판단하지 않는다.
77
+ const vertical = named("vertical");
78
+ if (!vertical) return;
79
+ if (vertical.value !== null && vertical.value?.expression?.value !== true) return;
80
+
81
+ // 이미 height prop 을 쓰고 있으면 컴포넌트가 정렬까지 맡는다
82
+ if (named("height")) return;
83
+
84
+ const classAttr = attrs.find(isClassAttr);
85
+ if (!classAttr) return;
86
+
87
+ const tokens = collectClassTokens(classAttr);
88
+ let height = null;
89
+ for (const { token } of tokens) {
90
+ const util = stripModifiers(stripVariants(token));
91
+ if (alignsSelf(util)) return; // 정렬을 직접 정했다 — 의도한 것으로 본다
92
+ // variant 가 붙은 높이(`md:h-sd-20`)는 prop 으로 옮길 수 없어 판단에서 뺀다
93
+ if (height === null && token === util) height = heightUtil(util);
94
+ }
95
+ if (height === null) return;
96
+
97
+ const propValue = toHeightProp(height);
98
+
99
+ context.report({
100
+ node,
101
+ messageId: "useHeightProp",
102
+ data: { suggestion: propValue ? ` (\`height=${propValue}\`)` : "" },
103
+ fix(fixer) {
104
+ if (!propValue) return null;
105
+ // className 이 통짜 문자열일 때만 안전하게 손댄다 (cn()·템플릿 리터럴은 제외)
106
+ const raw =
107
+ classAttr.value?.type === "Literal"
108
+ ? classAttr.value
109
+ : classAttr.value?.type === "JSXExpressionContainer" &&
110
+ classAttr.value.expression.type === "Literal"
111
+ ? classAttr.value.expression
112
+ : null;
113
+ if (!raw || typeof raw.value !== "string") return null;
114
+
115
+ const rest = raw.value
116
+ .split(/\s+/)
117
+ .filter(Boolean)
118
+ .filter((t) => t !== `h-${height}`);
119
+ if (rest.length === raw.value.split(/\s+/).filter(Boolean).length) return null;
120
+
121
+ const fixes = [fixer.insertTextAfter(vertical, ` height=${propValue}`)];
122
+ if (rest.length > 0) {
123
+ fixes.push(fixer.replaceText(raw, `"${rest.join(" ")}"`));
124
+ } else {
125
+ // 속성만 지우면 공백이 두 칸 남는다 — 앞 공백까지 함께 지운다
126
+ const src = context.sourceCode ?? context.getSourceCode();
127
+ const [start, end] = classAttr.range;
128
+ const from = /\s/.test(src.text[start - 1]) ? start - 1 : start;
129
+ fixes.push(fixer.removeRange([from, end]));
130
+ }
131
+ return fixes;
132
+ },
133
+ });
134
+ },
135
+ };
136
+ },
137
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sellmate-design-system-react",
3
- "version": "9.0.0-beta.21",
3
+ "version": "9.0.0-beta.24",
4
4
  "description": "Sellmate Design System — React (TypeScript + Tailwind v4) port",
5
5
  "license": "UNLICENSED",
6
6
  "keywords": [
@@ -89,11 +89,9 @@
89
89
  "@radix-ui/react-switch": "^1.3.2",
90
90
  "@radix-ui/react-tooltip": "^1.2.11",
91
91
  "@tiptap/core": "^3.30.2",
92
- "@tiptap/extension-highlight": "^3.30.2",
93
92
  "@tiptap/extension-image": "^3.30.2",
94
93
  "@tiptap/extension-list": "^3.30.2",
95
- "@tiptap/extension-subscript": "^3.30.2",
96
- "@tiptap/extension-superscript": "^3.30.2",
94
+ "@tiptap/extension-table": "^3.30.2",
97
95
  "@tiptap/extension-text-align": "^3.30.2",
98
96
  "@tiptap/extension-text-style": "^3.30.2",
99
97
  "@tiptap/extension-typography": "^3.30.2",