@iyulab/components 1.36.0 → 1.37.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.37.0] - 2026-09-06
4
+
5
+ ### Added
6
+
7
+ - **`u-date-picker` and `u-select` expose a `:state(open)` custom state.**
8
+ Both already tracked their popover's open/closed state privately; it is now
9
+ surfaced through `ElementInternals.states` so consumers can style the trigger
10
+ while the popover is showing — `u-date-picker:state(open)::part(container)`,
11
+ `u-select:state(open)::part(container)`. Deliberately not a reflected
12
+ attribute: the state stays private to the component and exists only as a CSS
13
+ hook, so no new public attribute enters the API surface.
14
+
15
+ ### Documentation
16
+
17
+ - **`UFloatingElement.placement` documents that `flip` is always applied.**
18
+ Whenever `placement` is set, floating-ui's `flip` middleware runs (switching
19
+ to the opposite side when the placed side has no room) — this has always been
20
+ the behavior but was undocumented, and `shift`'s description ("keeps the
21
+ element on screen") over-promised, since `shift` only corrects the cross axis
22
+ *within* a side. Both properties now describe the split, and a regression test
23
+ covers the flip fallback.
24
+
3
25
  ## [1.36.0] - 2026-09-04
4
26
 
5
27
  ### Added
@@ -51,6 +51,12 @@ export declare class UFloatingElement extends UElement {
51
51
  * 대상 엘리먼트로부터의 배치 위치입니다.
52
52
  * 지정하지 않으면 자동으로 가장 적절한 위치가 선택됩니다.
53
53
  *
54
+ * @remarks
55
+ * 지정한 변(side)에 공간이 없으면 반대 변으로 자동 전환됩니다(floating-ui의
56
+ * `flip` 미들웨어가 `placement`를 지정했을 때 항상 함께 적용됩니다 — 별도
57
+ * 옵션으로 끌 수 없습니다). `shift`는 이 전환과 별개로, 전환된(또는 지정된)
58
+ * 변 **안에서** 교차축 위치만 보정합니다.
59
+ *
54
60
  * @default undefined
55
61
  */
56
62
  placement?: Placement;
@@ -62,7 +68,9 @@ export declare class UFloatingElement extends UElement {
62
68
  */
63
69
  offset: OffsetOptions;
64
70
  /**
65
- * 엘리먼트가 화면 안에 머물도록 자동으로 위치를 조정할지 여부입니다.
71
+ * 지정된(또는 `flip`으로 전환된) 배치 **안에서** 교차축 위치를 자동으로
72
+ * 보정할지 여부입니다 — 그 변 자체에 공간이 없어 반대 변으로 넘어가는 것은
73
+ * `placement` 설명의 `flip` 동작이 담당합니다.
66
74
  *
67
75
  * @default false
68
76
  */
@@ -16,6 +16,11 @@ export type DatePickerMode = 'date' | 'datetime';
16
16
  * first day of week from `Intl.Locale(locale).weekInfo?.firstDay`, falling back to Sunday
17
17
  * where unsupported.
18
18
  *
19
+ * Exposes a `:state(open)` custom state (via `ElementInternals.states`) while the calendar
20
+ * popover is showing — style with `u-date-picker:state(open)::part(container)`. Unlike
21
+ * `mode`/`clearable`, this state is never reflected as a public attribute — it exists purely
22
+ * as a CSS hook for consumers who want to react to the open/closed state from outside.
23
+ *
19
24
  * @csspart field - the u-field element
20
25
  * @csspart container - the element wrapping the trigger area
21
26
  * @csspart popover - the popover element showing the calendar
@@ -178,6 +178,7 @@ var UDatePicker = class UDatePicker extends UFormControlElement {
178
178
  updated(changed) {
179
179
  super.updated(changed);
180
180
  if (changed.has("value")) this.internals?.setFormValue(this.value ?? "");
181
+ if (changed.has("open")) this.internals?.states[this.open ? "add" : "delete"]("open");
181
182
  if (changed.has("open") && this.open || changed.has("focusedDate") && this.open && this.grabFocusOnUpdate) {
182
183
  this.grabFocusOnUpdate = false;
183
184
  this.popoverEl?.updateComplete.then(() => this.focusDayButton(this.focusedDate));
@@ -12,6 +12,10 @@ export type SelectVariant = 'outlined' | 'filled' | 'underlined' | 'borderless';
12
12
  * 팝오버 목록에서 사라지기 때문. 리치 콘텐츠가 필요하면 이 slot에 별도 마크업을 할당하고
13
13
  * `change` 이벤트에서 직접 갱신한다.)
14
14
  *
15
+ * 옵션 목록 팝오버가 열려 있는 동안 `:state(open)` 커스텀 상태를 노출한다(via
16
+ * `ElementInternals.states`) — `u-select:state(open)::part(container)`로 스타일링할 수
17
+ * 있다. 공개 속성으로 반사되지 않는다.
18
+ *
15
19
  * @csspart field - u-field 요소
16
20
  * @csspart container - 트리거 영역을 감싸는 요소
17
21
  * @csspart popover - 옵션 목록이 표시되는 팝오버 요소
@@ -153,6 +153,7 @@ var USelect = class USelect extends UFormControlElement {
153
153
  updated(changedProperties) {
154
154
  super.updated(changedProperties);
155
155
  if (["value", "options"].some((k) => changedProperties.has(k))) this.onChangeValue();
156
+ if (changedProperties.has("open")) this.internals?.states[this.open ? "add" : "delete"]("open");
156
157
  }
157
158
  render() {
158
159
  return html`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@iyulab/components",
3
3
  "description": "web-components library based on lit-element made by iyulab",
4
- "version": "1.36.0",
4
+ "version": "1.37.0",
5
5
  "keywords": [
6
6
  "iyulab",
7
7
  "components",
@@ -40,7 +40,7 @@ Inherits all `UFloatingElement` properties (see [floating.md](../extensions/floa
40
40
  | `disabled` | `boolean` | `false` | ✓ | Disable opening |
41
41
  | `placement` | `Placement` | — | — | Preferred placement (`top`, `bottom`, `left`, `right`, `*-start`, `*-end`) |
42
42
  | `offset` | `OffsetOptions` | `0` | — | Distance from anchor |
43
- | `shift` | `boolean` | `false` | — | Auto-shift to stay in viewport |
43
+ | `shift` | `boolean` | `false` | — | Correct the cross-axis position *within* the placed side (see note below) |
44
44
  | `arrow` | `boolean` | `false` | — | Show arrow pointing to anchor |
45
45
  | `showDelay` | `number` | `0` | — | Open delay in ms |
46
46
  | `hideDelay` | `number` | `0` | — | Close delay in ms |
@@ -48,6 +48,12 @@ Inherits all `UFloatingElement` properties (see [floating.md](../extensions/floa
48
48
  | `dismiss` | `string[]` | `['click','escape','scroll','resize']` | ✓ | Close triggers — see note below |
49
49
  | `autofocus` | `boolean` | `false` | ✓ | Focus first focusable element on open |
50
50
 
51
+ > **Placement fallback**: whenever `placement` is set, floating-ui's `flip` middleware is
52
+ > always applied — if the placed side has no room, the element switches to the opposite side.
53
+ > `shift` is a separate, narrower correction: it nudges the element along the cross axis
54
+ > *within* whichever side ended up being used. Neither can be turned off independently.
55
+
56
+
51
57
  ### `dismiss` semantics
52
58
 
53
59
  `click` and `escape` express user intent and always close the popover.
@@ -43,13 +43,19 @@ Inherits all `UFloatingElement` properties (see [floating.md](../extensions/floa
43
43
  | `open` | `boolean` | `false` | ✓ | Visibility state |
44
44
  | `placement` | `Placement` | — | — | Preferred placement |
45
45
  | `offset` | `OffsetOptions` | `0` | — | Gap from target |
46
- | `shift` | `boolean` | `false` | — | Auto-shift to stay in viewport |
46
+ | `shift` | `boolean` | `false` | — | Correct the cross-axis position *within* the placed side (see note below) |
47
47
  | `arrow` | `boolean` | `false` | — | Show pointing arrow |
48
48
  | `showDelay` | `number` | `0` | — | Open delay in ms |
49
49
  | `hideDelay` | `number` | `0` | — | Close delay in ms |
50
50
  | `interactive` | `boolean` | `false` | ✓ | Keep open when mouse is over tooltip |
51
51
  | `tracking` | `boolean` | `false` | ✓ | Follow mouse cursor position |
52
52
 
53
+ > **Placement fallback**: whenever `placement` is set, floating-ui's `flip` middleware is
54
+ > always applied — if the placed side has no room, the element switches to the opposite side.
55
+ > `shift` is a separate, narrower correction: it nudges the element along the cross axis
56
+ > *within* whichever side ended up being used. Neither can be turned off independently.
57
+
58
+
53
59
  ## Events
54
60
 
55
61
  | Event | Cancelable | Description |