@orioncactuscorp/ui 1.15.1 → 1.17.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 (105) hide show
  1. package/CHANGELOG.md +146 -0
  2. package/README.md +54 -15
  3. package/dist/components/Accordion/Accordion.css +1 -1
  4. package/dist/components/ActionArea/ActionArea.css +1 -1
  5. package/dist/components/ActionArea/ActionArea.js +56 -55
  6. package/dist/components/BackgroundIconButton/BackgroundIconButton.css +1 -1
  7. package/dist/components/BackgroundIconButton/BackgroundIconButton.js +9 -9
  8. package/dist/components/Badge/Badge.css +1 -1
  9. package/dist/components/Badge/Badge.js +44 -39
  10. package/dist/components/Badge/Badge.module.scss.js +9 -8
  11. package/dist/components/Button/Button.css +1 -1
  12. package/dist/components/Button/Button.js +5 -5
  13. package/dist/components/Cell/Cell.css +1 -1
  14. package/dist/components/CheckMark/CheckMark.css +1 -1
  15. package/dist/components/CheckMark/CheckMark.js +6 -6
  16. package/dist/components/Checkbox/Checkbox.css +1 -1
  17. package/dist/components/Checkbox/Checkbox.js +15 -15
  18. package/dist/components/Field/Field.css +1 -1
  19. package/dist/components/Fieldset/Fieldset.css +1 -1
  20. package/dist/components/IconButton/IconButton.css +1 -1
  21. package/dist/components/IconButton/IconButton.js +9 -9
  22. package/dist/components/Interaction/Interaction.css +1 -1
  23. package/dist/components/Interaction/Interaction.js +19 -12
  24. package/dist/components/Modal/Modal.css +1 -1
  25. package/dist/components/Modal/Modal.js +555 -579
  26. package/dist/components/Modal/blockSize.js +7 -0
  27. package/dist/components/Modal/bottomSheetRelease.js +114 -0
  28. package/dist/components/Modal/cssTime.js +11 -0
  29. package/dist/components/Modal/modalResizeTarget.js +28 -0
  30. package/dist/components/Modal/modalScrollArbitration.js +57 -66
  31. package/dist/components/Modal/useBottomSheetIntrinsicHeight.js +55 -0
  32. package/dist/components/Modal/useMeasuredElement.js +20 -0
  33. package/dist/components/Modal/useModalContentBlockTransition.js +128 -49
  34. package/dist/components/Modal/useModalContentSizeSignal.js +30 -0
  35. package/dist/components/Modal/useModalDrag.js +994 -1017
  36. package/dist/components/PositionSnap/PositionSnap.css +1 -1
  37. package/dist/components/ProgressIndicator/ProgressIndicator.css +1 -1
  38. package/dist/components/Radio/Radio.css +1 -1
  39. package/dist/components/Radio/Radio.js +9 -9
  40. package/dist/components/ScrollArea/ScrollArea.css +1 -1
  41. package/dist/components/ScrollArea/ScrollArea.js +262 -264
  42. package/dist/components/Skeleton/Skeleton.css +1 -1
  43. package/dist/components/Switch/Switch.css +1 -1
  44. package/dist/components/Switch/Switch.js +7 -7
  45. package/dist/components/Tabs/Tabs.css +1 -1
  46. package/dist/components/TextButton/TextButton.css +1 -1
  47. package/dist/components/TextButton/TextButton.js +17 -17
  48. package/dist/components/internal/ModalPresentation.js +1 -1
  49. package/dist/foundations/touch.css +1 -0
  50. package/dist/foundations.css +1 -0
  51. package/dist/styles.css +22 -21
  52. package/dist/ui/src/components/ActionArea/ActionArea.d.ts.map +1 -1
  53. package/dist/ui/src/components/Badge/Badge.d.ts.map +1 -1
  54. package/dist/ui/src/components/Badge/types.d.ts +1 -1
  55. package/dist/ui/src/components/Badge/types.d.ts.map +1 -1
  56. package/dist/ui/src/components/Interaction/Interaction.d.ts.map +1 -1
  57. package/dist/ui/src/components/Interaction/types.d.ts +2 -0
  58. package/dist/ui/src/components/Interaction/types.d.ts.map +1 -1
  59. package/dist/ui/src/components/Modal/Modal.d.ts +1 -1
  60. package/dist/ui/src/components/Modal/Modal.d.ts.map +1 -1
  61. package/dist/ui/src/components/Modal/blockSize.d.ts +2 -0
  62. package/dist/ui/src/components/Modal/blockSize.d.ts.map +1 -0
  63. package/dist/ui/src/components/Modal/bottomSheetRelease.d.ts +19 -0
  64. package/dist/ui/src/components/Modal/bottomSheetRelease.d.ts.map +1 -0
  65. package/dist/ui/src/components/Modal/contexts.d.ts +1 -0
  66. package/dist/ui/src/components/Modal/contexts.d.ts.map +1 -1
  67. package/dist/ui/src/components/Modal/cssTime.d.ts +4 -0
  68. package/dist/ui/src/components/Modal/cssTime.d.ts.map +1 -0
  69. package/dist/ui/src/components/Modal/modalResizeTarget.d.ts +12 -0
  70. package/dist/ui/src/components/Modal/modalResizeTarget.d.ts.map +1 -0
  71. package/dist/ui/src/components/Modal/modalScrollArbitration.d.ts.map +1 -1
  72. package/dist/ui/src/components/Modal/types.d.ts +6 -0
  73. package/dist/ui/src/components/Modal/types.d.ts.map +1 -1
  74. package/dist/ui/src/components/Modal/useBottomSheetIntrinsicHeight.d.ts +21 -0
  75. package/dist/ui/src/components/Modal/useBottomSheetIntrinsicHeight.d.ts.map +1 -0
  76. package/dist/ui/src/components/Modal/{useElementSize.d.ts → useMeasuredElement.d.ts} +1 -1
  77. package/dist/ui/src/components/Modal/useMeasuredElement.d.ts.map +1 -0
  78. package/dist/ui/src/components/Modal/useModalContentBlockTransition.d.ts +20 -1
  79. package/dist/ui/src/components/Modal/useModalContentBlockTransition.d.ts.map +1 -1
  80. package/dist/ui/src/components/Modal/useModalContentSizeSignal.d.ts +22 -0
  81. package/dist/ui/src/components/Modal/useModalContentSizeSignal.d.ts.map +1 -0
  82. package/dist/ui/src/components/Modal/useModalDrag.d.ts.map +1 -1
  83. package/dist/ui/src/components/ScrollArea/ScrollArea.d.ts +1 -1
  84. package/dist/ui/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  85. package/dist/ui/src/components/ScrollArea/index.d.ts +1 -1
  86. package/dist/ui/src/components/ScrollArea/index.d.ts.map +1 -1
  87. package/dist/ui/src/components/ScrollArea/types.d.ts +2 -0
  88. package/dist/ui/src/components/ScrollArea/types.d.ts.map +1 -1
  89. package/dist/ui/src/index.d.ts +1 -1
  90. package/dist/ui/src/index.d.ts.map +1 -1
  91. package/dist/vscode/oc-ui-vars.css +1 -0
  92. package/docs/api-conventions.md +5 -0
  93. package/docs/responsive-foundation-profile.md +1 -0
  94. package/docs/scss-helpers.md +1 -3
  95. package/docs/selector-contract.md +63 -12
  96. package/docs/tokens.md +6 -0
  97. package/package.json +1 -1
  98. package/src/scss/foundations/touch.scss +3 -0
  99. package/src/scss/foundations/touch.test.ts +37 -0
  100. package/src/scss/foundations/typo.scss +1 -1
  101. package/src/scss/index.scss +1 -0
  102. package/src/scss/mixins/_fluid.test.ts +0 -16
  103. package/src/scss/mixins/_utils.scss +0 -6
  104. package/dist/components/Modal/useElementSize.js +0 -23
  105. package/dist/ui/src/components/Modal/useElementSize.d.ts.map +0 -1
@@ -18,7 +18,7 @@
18
18
  /* 예: invalid 상태의 TextInput content 표면 커스터마이즈 */
19
19
  [data-oc-component='text-input'][data-oc-invalid='true']
20
20
  [data-oc-part='content'] {
21
- --oc-text-input-border-color: var(--oc-color-theme-status-negative);
21
+ --oc-field-control-stroke-color: var(--oc-color-theme-status-negative);
22
22
  }
23
23
  ```
24
24
 
@@ -30,7 +30,8 @@
30
30
 
31
31
  ## Override가 동작하는 방식
32
32
 
33
- - 컴포넌트 소스는 루트 modifier selector를 `:where(...)`로 낮은 specificity로 유지합니다. 나중에 로드되는 consumer 클래스 하나로 루트 레벨 `--oc-*` component contract 변수를 덮을 있습니다.
33
+ - 공개 component contract 변수는 property fallback 또는 `--_-{component}-*` internal default를 통해 기본값을 제공합니다. 따라서 per-component CSS chunk가 consumer CSS보다 나중에 로드되어도 consumer host class의 값이 유지됩니다.
34
+ - 컴포넌트 소스는 루트 modifier selector를 `:where(...)`로 낮은 specificity로 유지합니다. consumer 클래스 하나로 루트 레벨의 공개 `--oc-*` component contract 변수를 덮을 수 있습니다.
34
35
  - 스타일 override는 paint property를 직접 재선언하기보다 컴포넌트가 노출하는 contract 변수(`--oc-{component}-*`)를 덮는 방식을 우선하세요. 상태 전이·모션과의 일관성이 유지됩니다.
35
36
  - 방향성 계약(`--oc-*` 변수, `data-oc-*` 값, prop)은 물리 방향(top/right/bottom/left)이 아니라 논리 방향(`block-start`, `inline-end`, `start`, `end` 등)을 사용합니다. RTL에서 자동으로 뒤집힙니다.
36
37
 
@@ -45,6 +46,8 @@
45
46
  | `Switch` | `--oc-switch-background-color` | `--oc-switch-color` | checked track, thumb |
46
47
  | `BackgroundIconButton` | `--oc-background-icon-button-background-color` | `--oc-background-icon-button-color` | 모든 variant의 background, icon |
47
48
 
49
+ `BackgroundIconButton`의 disabled 상태는 불투명한 fill 레이어를 컴포넌트 루트 위에 덮어 그립니다. blend mode와 backdrop-filter가 비선형으로 합성되기 때문에, 장식 레이어를 그대로 둔 채 이 레이어의 `opacity`만 올려야 전환이 두 끝 상태의 선형 보간이 되어 중간에 튀지 않습니다. 이 fill 색은 `--oc-background-icon-button-disabled-background-color`로 재정의할 수 있고, 기본값은 `--oc-color-theme-interaction-disable`입니다. disabled에서는 이 레이어가 배경을 덮으므로 `--oc-background-icon-button-background-color` 값은 보이지 않습니다.
50
+
48
51
  ```css
49
52
  .darkPrimaryControl {
50
53
  --oc-radio-background-color: var(--oc-color-theme-label-strong);
@@ -55,7 +58,7 @@
55
58
 
56
59
  ## Interaction 프리미티브
57
60
 
58
- `Interaction`은 hover/press/focus 피드백을 그리는 passive 시각 레이어입니다. `pointer-events: none`이고 자기 상태를 갖지 않으며, 부모 컴포넌트가 자기 상태 selector로 자식 Interaction의 opacity를 제어합니다.
61
+ `Interaction`은 hover/press/focus 피드백을 그리는 시각 레이어입니다. 시각 pseudo는 passive이며 부모 컴포넌트가 자기 상태 selector로 Interaction의 opacity를 제어합니다. `self`가 아닌 Interaction은 자기 상태를 만들지 않지만, 선택적으로 확장된 투명 hit pseudo의 pointer event가 host로 버블링될 수 있습니다.
59
62
 
60
63
  ```scss
61
64
  .myControl {
@@ -103,17 +106,59 @@
103
106
  | `--oc-interaction-opacity-hover` | `--oc-color-global-opacity-5 × resolved factor` | Interaction이 제공하는 hover 출력값 |
104
107
  | `--oc-interaction-opacity-focus` | `--oc-color-global-opacity-8 × resolved factor` | Interaction이 제공하는 focus 출력값 |
105
108
  | `--oc-interaction-opacity-active` | `--oc-color-global-opacity-12 × resolved factor` | Interaction이 제공하는 active 출력값 |
109
+ | `--oc-interaction-touch-target-min` | component별 opt-in, foundation은 `44px` | host 범위의 최소 pointer hit area |
106
110
 
107
111
  `--oc-interaction-opacity-*`는 custom host가 상태 selector에서 읽는 resolved output 계약입니다. 임의 강도를 지정할 때는 이 출력값을 자식 selector로 덮지 말고 host에서 `--oc-interaction-opacity-factor`를 설정하세요.
108
112
 
113
+ 터치 대상 최소 크기는 foundation `--oc-touch-target-min`의 기본값 `44px`을 사용합니다. Button, button/anchor TextButton, IconButton, BackgroundIconButton, interactive Badge, CheckMark, Checkbox, Radio, Switch는 이 값을 internal default로 선택합니다. 실제 component host에서 `--oc-interaction-touch-target-min`을 지정하면 CSS 로딩 순서와 무관하게 해당 값이 우선하며, `0px`은 Interaction의 기존 geometry 바깥으로 hit area를 확장하지 않습니다. 시각 Interaction의 inset, color, radius, opacity, motion geometry는 터치 영역과 분리되어 유지됩니다.
114
+
115
+ 저수준 custom host는 `<Interaction touchTarget />`으로 hit layer를 opt-in합니다. 이때 `data-oc-touch-target="true"`가 렌더링되며, prop을 생략한 기존 `<Interaction />`은 passive visual layer와 기존 pointer geometry를 그대로 유지합니다.
116
+
117
+ `button`, `a`, `label`, `summary` 또는 interactive ARIA role host가 `<Interaction touchTarget />`을 직계 자식으로 사용하면 iOS Safari의 native tap highlight와 accidental text selection은 비활성화되고 Interaction feedback이 이를 대체합니다. 링크의 long-press context menu와 브라우저 gesture는 유지하므로 `-webkit-touch-callout`과 `touch-action`은 변경하지 않습니다. Interaction이 더 깊게 중첩되는 custom composition은 실제 interactive host에 `-webkit-tap-highlight-color: transparent`, `user-select: none`, `-webkit-user-select: none`을 직접 선언해야 합니다. 선택 가능한 control label이 필요한 예외는 host class에서 `user-select: text`를 다시 선언할 수 있습니다.
118
+
119
+ ```scss
120
+ .compactAction {
121
+ --oc-interaction-touch-target-min: 32px;
122
+ }
123
+
124
+ .largeTouchAction {
125
+ --oc-interaction-touch-target-min: 48px;
126
+ }
127
+ ```
128
+
129
+ 확장 영역은 layout 공간을 만들지 않습니다. oc-ui가 소유한 복합 layout은 형제 hit area가 겹치지 않게 자체 spacing 계약을 사용하며, consumer가 작은 control을 조밀하게 배치할 때는 layout gap을 확보하거나 host별 최소 크기를 조정해야 합니다. host 바깥 hit testing을 위해 기본 적용 대상은 Interaction ancestor에서 overflow clipping을 사용하지 않으며, 시각 radius는 passive visual layer에서 유지합니다. disabled host는 확장 hit area도 비활성화합니다. Tabs는 기존 `--oc-tabs-tab-interaction-margin-inline`과 list gap 계약을, ScrollArea scrollbar는 데스크톱 drag geometry를 우선하므로 44px 기본 확장을 선택하지 않습니다.
130
+
109
131
  ## Badge 계약
110
132
 
111
- | Component | Root selector | Visual selectors | Stable parts |
112
- | --------- | --------------------------- | --------------------------------------------------------------------------------------------------------- | ------------ |
113
- | `Badge` | `data-oc-component="badge"` | `data-oc-variant="normal\|accent\|overlay"`, `data-oc-size="xsmall\|small"`, `data-oc-interactive="true"` | `content` |
133
+ | Component | Root selector | Visual selectors | Stable parts |
134
+ | --------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- |
135
+ | `Badge` | `data-oc-component="badge"` | `data-oc-variant="default\|normal\|accent\|overlay"`, `data-oc-size="xsmall\|small"`, `data-oc-interactive="true"` | `content`, `surface`, `surface-default`, `surface-normal`, `surface-overlay` |
114
136
 
115
137
  `Badge`의 작은 named size는 `data-oc-size="xsmall"`을 사용합니다. 이전
116
138
  `data-oc-size="tiny"` 값은 major 변경으로 제거됐습니다.
139
+ `default`가 canonical 기본 variant이며, `normal`은 기존 소비자를 위한 호환
140
+ 선택지입니다. variant를 생략하면 `data-oc-variant="default"`가 출력됩니다.
141
+ `default`는 `label-strong` 배경과 `background-normal-normal` 라벨 색을 사용하고,
142
+ `normal`은 기존 `label-alternative` 라벨과 `fill-normal` 배경을 유지합니다.
143
+
144
+ Badge의 `surface` part는 배경 레이어를 담당하며, `accent` 배경이 사라지고
145
+ `default` 또는 `overlay` 배경이 나타나는 전환을 별도 opacity 레이어로 처리합니다.
146
+ border는 다음 component contract 변수로 조정할 수 있습니다.
147
+
148
+ | Contract variable | Default | 용도 |
149
+ | ------------------------- | ------------- | ----------------- |
150
+ | `--oc-badge-border-width` | `1px` | inset border 두께 |
151
+ | `--oc-badge-border-color` | `transparent` | inset border 색상 |
152
+
153
+ border는 Badge의 기존 radius를 따르며 `oc-border` 기반의 고정 all/inset stroke로
154
+ 그려집니다. 색상만 지정하면 기본 1px border가 표시되고, width를 함께 override할
155
+ 수 있습니다. 예를 들어 다음처럼 색상만 지정할 수 있습니다.
156
+
157
+ ```scss
158
+ .badgeWithBorder {
159
+ --oc-badge-border-color: var(--oc-color-theme-line-normal-normal);
160
+ }
161
+ ```
117
162
 
118
163
  ## Field 레이아웃 계약
119
164
 
@@ -269,15 +314,17 @@ Tab content는 inline padding 없이 배치되고 배경색이 transparent인 se
269
314
 
270
315
  `ActionAreaLayout`은 스크롤 가능한 body와 고정 footer slot 사이의 scroll 경계를 소유합니다.
271
316
 
272
- | Component | Root selector | Visual selectors | Stable parts |
273
- | ------------------------- | ----------------------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------- |
274
- | `ActionArea` | `data-oc-component="action-area"` | `data-oc-variant`, `data-oc-background="true"` | `actions`, `caption`, `extra-slot`, `compact-row`, `compact-slot` |
275
- | `ActionAreaLayout` | `data-oc-component="action-area-layout"` | `data-oc-scrollable="true\|false"` | - |
276
- | `ActionAreaLayout.Body` | `data-oc-component="action-area-layout-body"` | - | `body` |
277
- | `ActionAreaLayout.Footer` | `data-oc-component="action-area-layout-footer"` | - | `footer` |
317
+ | Component | Root selector | Visual selectors | Stable parts |
318
+ | ------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------- |
319
+ | `ActionArea` | `data-oc-component="action-area"` | `data-oc-variant`, `data-oc-background="true"`, `data-oc-empty="true"` | `actions`, `caption`, `extra-slot`, `compact-row`, `compact-slot` |
320
+ | `ActionAreaLayout` | `data-oc-component="action-area-layout"` | `data-oc-scrollable="true\|false"` | - |
321
+ | `ActionAreaLayout.Body` | `data-oc-component="action-area-layout-body"` | - | `body` |
322
+ | `ActionAreaLayout.Footer` | `data-oc-component="action-area-layout-footer"` | - | `footer` |
278
323
 
279
324
  - `data-oc-scrollable="true"`는 body에 보이는 scrollport 밖 overflow가 있다는 뜻입니다. 이 상태에서 직속 footer `ActionArea`는 block-end padding을 유지하고 `--oc-action-area-padding-block-start: 0`을 받으며, 대응하는 block-start 간격은 body에 예약됩니다.
280
325
  - `ActionAreaLayout.ActionArea background="auto"`는 scroll 상태를 자식 `ActionArea`의 background 계약에 매핑합니다: body가 스크롤 가능하고 바닥에 닿지 않은 동안만 `data-oc-background="true"`가 방출됩니다. `data-oc-background`는 시각 gradient/background 상태이며 body 예약의 근거로 사용하지 마세요.
326
+ - 렌더링할 액션, caption, extraContent가 없는 `ActionArea`는 `data-oc-empty="true"`를 방출하고 자체 padding과 background를 접습니다. `ModalFooter`나 `FloatingWindowFooter`의 직속 빈 `ActionArea`는 footer 예약을 `0`으로 만들어 body는 기본 하단 여백만 유지합니다. depth navigation처럼 root에서는 액션이 없고 다음 depth부터 버튼이 생기는 구성에서 Footer를 계속 마운트해 둘 때 사용합니다. 여백이 필요하면 빈 `ActionArea` 대신 명시적 spacer를 두세요.
327
+ - `ModalBody` 또는 같은 presentation frame을 사용하는 `FloatingWindowBody`의 마지막 직속 자식이 `ActionArea`이면 owner surface가 inline padding과 block-end padding을 `0`, desktop action group의 max width를 `none`으로 자동 보정합니다. 본문 padding과 중복되지 않도록 하기 위한 기본값이며, `ActionArea`에 명시한 `--oc-action-area-*` 변수는 이 보정보다 우선합니다. bottom placement의 safe-area 및 footer 예약은 Modal surface/body가 계속 소유합니다.
281
328
 
282
329
  ## FloatingWindow 계약
283
330
 
@@ -362,6 +409,10 @@ Modal의 기본 `initialFocus="auto"`는 `ModalHeader`의 visible title을 `tabI
362
409
  - bottom placement에서 소프트 키보드 회피 세션이 활성일 때 viewport 레이어(`data-oc-part="viewport"`)에 `data-oc-modal-keyboard-avoiding="true"`가 방출됩니다. 키보드 geometry 추격 transition의 게이트로 쓰이는 내부 지향 상태이며, 소비자는 이 attribute의 방출 타이밍(세션 시작/해제 시점의 지연 포함)에 의존하지 않는 것이 좋습니다.
363
410
  - `ModalNavigationSection`은 body content가 아니라 Modal chrome입니다. 루트는 `data-oc-state="open|closed"`, toggle row는 `data-oc-component="modal-navigation"` + `data-oc-part="navigation"` + `aria-expanded`/`aria-controls`, indicator는 `data-oc-part="indicator"`/`indicator-frame`, panel은 `data-oc-component="modal-navigation-panel"`(collapsed 동안 `aria-hidden`/`inert`), panel content는 `data-oc-part="panel-inner"`를 노출합니다.
364
411
 
412
+ ## ScrollArea scrollbar 계약
413
+
414
+ `ScrollArea`는 현재 scrollbar 렌더링 경로를 `data-oc-scrollbar-mode="custom | native"`, 공개 표시 정책을 `data-oc-scrollbar-visibility="auto | hidden | hidden-on-touch"`로 제공합니다. `native` 모드에서는 운영체제 scrollbar와 네이티브 스크롤 물리를 유지합니다. `hidden`은 모든 환경에서, `hidden-on-touch`는 터치 환경에서만 스크롤 가능성을 유지한 채 시각적 indicator를 숨깁니다.
415
+
365
416
  ## Provider 소유 예외
366
417
 
367
418
  다음 non-`data-oc-*` attribute는 컴포넌트 소유 계약이 아니라 외부 provider/foundation 소유입니다.
package/docs/tokens.md CHANGED
@@ -479,6 +479,12 @@ responsive mode(fluid/stepped/static)에 따라 viewport별 출력이 달라집
479
479
  - `--oc-focus-ring-offset`
480
480
  - `--oc-focus-ring-width`
481
481
 
482
+ ## Touch target
483
+
484
+ 레이아웃 크기를 바꾸지 않고 pointer hit area를 확보할 때 사용하는 최소 크기입니다. Interaction host의 `--oc-interaction-touch-target-min` 계약이 이 foundation 기본값을 선택적으로 사용합니다.
485
+
486
+ - `--oc-touch-target-min`
487
+
482
488
  ## Motion
483
489
 
484
490
  duration/scale/distance factor는 unitless multiplier입니다. 자세한 정책은 [Semantic Motion](./motion.md)을 참조하세요.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orioncactuscorp/ui",
3
- "version": "1.15.1",
3
+ "version": "1.17.0",
4
4
  "description": "orioncactus UI foundations and core primitives",
5
5
  "private": false,
6
6
  "type": "module",
@@ -0,0 +1,3 @@
1
+ :root {
2
+ --oc-touch-target-min: 44px;
3
+ }
@@ -0,0 +1,37 @@
1
+ import { compileString } from 'sass';
2
+ import { describe, expect, it } from 'vitest';
3
+
4
+ describe('touch foundation', () => {
5
+ it('exposes the minimum touch target token', () => {
6
+ const result = compileString("@use 'foundations/touch' as *;", {
7
+ loadPaths: ['src/scss'],
8
+ });
9
+
10
+ expect(result.css).toContain('--oc-touch-target-min: 44px;');
11
+ });
12
+
13
+ it('keeps touch tokens in the full foundation rebuild composition', () => {
14
+ const result = compileString(
15
+ `
16
+ @use 'foundations/responsive.config' with (
17
+ $oc-responsive-mode: static,
18
+ $oc-responsive-static-stop: md
19
+ );
20
+ @use 'foundations/color.global' as *;
21
+ @use 'foundations/color.theme.light' as *;
22
+ @use 'foundations/color.theme.dark' as *;
23
+ @use 'foundations/breakpoint' as *;
24
+ @use 'foundations/typo' as *;
25
+ @use 'foundations/space' as *;
26
+ @use 'foundations/atomic' as *;
27
+ @use 'foundations/focus' as *;
28
+ @use 'foundations/touch' as *;
29
+ @use 'foundations/motion' as *;
30
+ @use 'foundations/zindex' as *;
31
+ `,
32
+ { loadPaths: ['src/scss'] },
33
+ );
34
+
35
+ expect(result.css).toContain('--oc-touch-target-min: 44px;');
36
+ });
37
+ });
@@ -358,7 +358,7 @@ $oc-typo-responsive-segments: (
358
358
  );
359
359
 
360
360
  /**
361
- * fluidClamp basis 375px = iPhone standard viewport (iOS HIG body 17pt 호환).
361
+ * Fluid basis 375px = iPhone standard viewport (iOS HIG body 17pt 호환).
362
362
  * iOS 네이티브 앱이 375+ 환경에서 body 17pt를 쓰는 것과 웹의 16px default 간극을
363
363
  * vw=375에서 17px 도달로 맞춰 시각적 이질감을 해소한다.
364
364
  */
@@ -6,6 +6,7 @@
6
6
  @forward './foundations/space';
7
7
  @forward './foundations/atomic';
8
8
  @forward './foundations/focus';
9
+ @forward './foundations/touch';
9
10
  @forward './foundations/motion';
10
11
  @forward './foundations/zindex';
11
12
  @forward './foundations/reset';
@@ -69,19 +69,3 @@ describe('oc-fluid function', () => {
69
69
  ).toThrow("oc-fluid() anchor must be 'from' or 'to'.");
70
70
  });
71
71
  });
72
-
73
- describe('fluidClamp compatibility function', () => {
74
- it('preserves the legacy argument order', () => {
75
- const css = compileScss(`
76
- @use 'utils' as *;
77
-
78
- .legacy {
79
- font-size: fluidClamp(toRem(16), 375px, to, toRem(20));
80
- }
81
- `);
82
-
83
- expect(css).toContain(
84
- '.legacy{font-size:clamp(1rem,20/375*100vw,1.25rem)}',
85
- );
86
- });
87
- });
@@ -1,7 +1 @@
1
- @use './fluid' as *;
2
-
3
1
  @forward './units';
4
-
5
- @function fluidClamp($from, $bp, $anchor: to, $to) {
6
- @return oc-fluid($from, $to, $bp, $anchor);
7
- }
@@ -1,23 +0,0 @@
1
- import { useState as o, useCallback as c, useLayoutEffect as a } from "react";
2
- function m() {
3
- const [e, s] = o(null), [u, r] = o(0), t = c((n) => {
4
- if (!n) {
5
- r(0);
6
- return;
7
- }
8
- r(n.getBoundingClientRect().height);
9
- }, []);
10
- return a(() => {
11
- if (!e) return;
12
- const n = window.requestAnimationFrame(() => t(e));
13
- if (typeof ResizeObserver > "u")
14
- return () => window.cancelAnimationFrame(n);
15
- const i = new ResizeObserver(() => t(e));
16
- return i.observe(e), () => {
17
- window.cancelAnimationFrame(n), i.disconnect();
18
- };
19
- }, [t, e]), { node: e, setNode: s, height: u };
20
- }
21
- export {
22
- m as useMeasuredElement
23
- };
@@ -1 +0,0 @@
1
- {"version":3,"file":"useElementSize.d.ts","sourceRoot":"","sources":["../../../../../src/components/Modal/useElementSize.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,WAAW;;;;EAgCvD"}