@selkit/dom 0.4.0 → 0.6.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/dist/index.cjs CHANGED
@@ -74,6 +74,7 @@ var LOAD_MORE_THRESHOLD = 32;
74
74
  var DEFAULT_ITEM_HEIGHT = 36;
75
75
  var DEFAULT_GROUP_HEIGHT = 28;
76
76
  var SR_ONLY_CSS = "position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0";
77
+ var builtinPositioner = (trigger, dropdown, opts) => attachPositioner(trigger, dropdown, opts?.autoWidth ?? false);
77
78
  function resolveParent(parent) {
78
79
  if (!parent) return null;
79
80
  if (typeof parent !== "string") return parent;
@@ -155,6 +156,7 @@ var SelkitDom = class {
155
156
  #itemHeight;
156
157
  #groupHeight;
157
158
  #dropdownParent;
159
+ #positionerFactory;
158
160
  #templateSelection;
159
161
  #templateOption;
160
162
  #templateArrow;
@@ -200,6 +202,7 @@ var SelkitDom = class {
200
202
  this.#itemHeight = cfg.itemHeight ?? DEFAULT_ITEM_HEIGHT;
201
203
  this.#groupHeight = cfg.groupHeight ?? DEFAULT_GROUP_HEIGHT;
202
204
  this.#dropdownParent = resolveParent(cfg.dropdownParent);
205
+ this.#positionerFactory = cfg.positioner ?? builtinPositioner;
203
206
  this.#templateSelection = cfg.templateSelection;
204
207
  this.#templateOption = cfg.templateOption;
205
208
  this.#templateArrow = cfg.templateArrow;
@@ -740,11 +743,9 @@ var SelkitDom = class {
740
743
  this.#dropdown.hidden = false;
741
744
  if (this.#positioner) this.#positioner.update();
742
745
  else
743
- this.#positioner = attachPositioner(
744
- this.#control,
745
- this.#dropdown,
746
- this.#dropdownAutoWidth
747
- );
746
+ this.#positioner = this.#positionerFactory(this.#control, this.#dropdown, {
747
+ autoWidth: this.#dropdownAutoWidth
748
+ });
748
749
  } else {
749
750
  this.#dropdown.hidden = true;
750
751
  this.#positioner?.destroy();
package/dist/index.d.cts CHANGED
@@ -1,5 +1,48 @@
1
1
  import { SelkitController, SelkitConfig, SelkitOption, SelkitEmptyReason } from '@selkit/core';
2
2
 
3
+ /**
4
+ * @selkit/dom — 預設輕量定位器(零依賴)
5
+ *
6
+ * 計算邏輯與 DOM 套用分離:computePosition 為純函式(可單元測)
7
+ * attachPositioner 負責讀取 rect、套 style、監聽 scroll/resize
8
+ */
9
+ type Placement = 'bottom' | 'top';
10
+ interface Rect {
11
+ top: number;
12
+ bottom: number;
13
+ left: number;
14
+ width: number;
15
+ }
16
+ interface PositionResult {
17
+ placement: Placement;
18
+ top: number;
19
+ left: number;
20
+ width: number;
21
+ }
22
+ /**
23
+ * 依觸發元件位置與下拉高度 決定放上方或下方(空間不足才翻轉)
24
+ * 並回傳套用座標 不做水平翻轉(select 下拉慣例對齊左緣、同寬)
25
+ */
26
+ declare function computePosition(triggerRect: Rect, dropdownHeight: number, viewportHeight: number, gap?: number): PositionResult;
27
+ interface Positioner {
28
+ update(): void;
29
+ destroy(): void;
30
+ }
31
+ /** 定位器工廠收到的選項 由 @selkit/dom 在開啟下拉時傳入 */
32
+ interface PositionerOptions {
33
+ /** 下拉寬度貼齊內容(至少與控制項同寬)而非固定等寬 */
34
+ autoWidth?: boolean;
35
+ /** trigger 與下拉之間的間距 px 預設 4 */
36
+ gap?: number;
37
+ }
38
+ /**
39
+ * 定位器工廠 可插拔點:@selkit/dom 預設用內建 attachPositioner
40
+ * 傳入自訂工廠(如 @selkit/floating 的 createFloatingPositioner)即換成進階定位
41
+ */
42
+ type PositionerFactory = (trigger: HTMLElement, dropdown: HTMLElement, opts?: PositionerOptions) => Positioner;
43
+ /** 將 dropdown 定位到 trigger 旁 並隨 scroll/resize 更新 */
44
+ declare function attachPositioner(trigger: HTMLElement, dropdown: HTMLElement, autoWidth?: boolean): Positioner;
45
+
3
46
  interface SelkitDomConfig<T = unknown> extends SelkitConfig<T> {
4
47
  /** class 前綴 預設 "selkit" */
5
48
  classPrefix?: string;
@@ -19,6 +62,8 @@ interface SelkitDomConfig<T = unknown> extends SelkitConfig<T> {
19
62
  groupHeight?: number;
20
63
  /** 把下拉浮層掛到指定容器(元素或選擇器)逃離 overflow/transform 祖先的裁切 常用 document.body */
21
64
  dropdownParent?: HTMLElement | string;
65
+ /** 自訂定位器工廠 預設為內建零依賴定位器(垂直翻轉)傳入 @selkit/floating 的 createFloatingPositioner 即啟用 flip/shift/size 進階定位 */
66
+ positioner?: PositionerFactory;
22
67
  /** 自訂已選顯示內容(tag 或單值) 回傳字串走 textContent 防 XSS 需 markup(icon 等)請回傳 Node */
23
68
  templateSelection?: (option: SelkitOption<T>, meta: {
24
69
  index: number;
@@ -67,35 +112,4 @@ declare class SelkitDom<T> implements SelkitDomInstance<T> {
67
112
  /** 在指定元素或 selector 對應的元素內建立並掛載一個 Selkit 下拉 */
68
113
  declare function createSelkitDom<T = unknown>(host: HTMLElement | string, config?: SelkitDomConfig<T>): SelkitDomInstance<T>;
69
114
 
70
- /**
71
- * @selkit/dom — 預設輕量定位器(零依賴)
72
- *
73
- * 計算邏輯與 DOM 套用分離:computePosition 為純函式(可單元測)
74
- * attachPositioner 負責讀取 rect、套 style、監聽 scroll/resize
75
- */
76
- type Placement = 'bottom' | 'top';
77
- interface Rect {
78
- top: number;
79
- bottom: number;
80
- left: number;
81
- width: number;
82
- }
83
- interface PositionResult {
84
- placement: Placement;
85
- top: number;
86
- left: number;
87
- width: number;
88
- }
89
- /**
90
- * 依觸發元件位置與下拉高度 決定放上方或下方(空間不足才翻轉)
91
- * 並回傳套用座標 不做水平翻轉(select 下拉慣例對齊左緣、同寬)
92
- */
93
- declare function computePosition(triggerRect: Rect, dropdownHeight: number, viewportHeight: number, gap?: number): PositionResult;
94
- interface Positioner {
95
- update(): void;
96
- destroy(): void;
97
- }
98
- /** 將 dropdown 定位到 trigger 旁 並隨 scroll/resize 更新 */
99
- declare function attachPositioner(trigger: HTMLElement, dropdown: HTMLElement, autoWidth?: boolean): Positioner;
100
-
101
- export { type Placement, type PositionResult, type Positioner, type Rect, SelkitDom as Selkit, SelkitDom, type SelkitDomConfig, type SelkitDomInstance, attachPositioner, computePosition, createSelkitDom, createSelkitDom as sk };
115
+ export { type Placement, type PositionResult, type Positioner, type PositionerFactory, type PositionerOptions, type Rect, SelkitDom as Selkit, SelkitDom, type SelkitDomConfig, type SelkitDomInstance, attachPositioner, computePosition, createSelkitDom, createSelkitDom as sk };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,48 @@
1
1
  import { SelkitController, SelkitConfig, SelkitOption, SelkitEmptyReason } from '@selkit/core';
2
2
 
3
+ /**
4
+ * @selkit/dom — 預設輕量定位器(零依賴)
5
+ *
6
+ * 計算邏輯與 DOM 套用分離:computePosition 為純函式(可單元測)
7
+ * attachPositioner 負責讀取 rect、套 style、監聽 scroll/resize
8
+ */
9
+ type Placement = 'bottom' | 'top';
10
+ interface Rect {
11
+ top: number;
12
+ bottom: number;
13
+ left: number;
14
+ width: number;
15
+ }
16
+ interface PositionResult {
17
+ placement: Placement;
18
+ top: number;
19
+ left: number;
20
+ width: number;
21
+ }
22
+ /**
23
+ * 依觸發元件位置與下拉高度 決定放上方或下方(空間不足才翻轉)
24
+ * 並回傳套用座標 不做水平翻轉(select 下拉慣例對齊左緣、同寬)
25
+ */
26
+ declare function computePosition(triggerRect: Rect, dropdownHeight: number, viewportHeight: number, gap?: number): PositionResult;
27
+ interface Positioner {
28
+ update(): void;
29
+ destroy(): void;
30
+ }
31
+ /** 定位器工廠收到的選項 由 @selkit/dom 在開啟下拉時傳入 */
32
+ interface PositionerOptions {
33
+ /** 下拉寬度貼齊內容(至少與控制項同寬)而非固定等寬 */
34
+ autoWidth?: boolean;
35
+ /** trigger 與下拉之間的間距 px 預設 4 */
36
+ gap?: number;
37
+ }
38
+ /**
39
+ * 定位器工廠 可插拔點:@selkit/dom 預設用內建 attachPositioner
40
+ * 傳入自訂工廠(如 @selkit/floating 的 createFloatingPositioner)即換成進階定位
41
+ */
42
+ type PositionerFactory = (trigger: HTMLElement, dropdown: HTMLElement, opts?: PositionerOptions) => Positioner;
43
+ /** 將 dropdown 定位到 trigger 旁 並隨 scroll/resize 更新 */
44
+ declare function attachPositioner(trigger: HTMLElement, dropdown: HTMLElement, autoWidth?: boolean): Positioner;
45
+
3
46
  interface SelkitDomConfig<T = unknown> extends SelkitConfig<T> {
4
47
  /** class 前綴 預設 "selkit" */
5
48
  classPrefix?: string;
@@ -19,6 +62,8 @@ interface SelkitDomConfig<T = unknown> extends SelkitConfig<T> {
19
62
  groupHeight?: number;
20
63
  /** 把下拉浮層掛到指定容器(元素或選擇器)逃離 overflow/transform 祖先的裁切 常用 document.body */
21
64
  dropdownParent?: HTMLElement | string;
65
+ /** 自訂定位器工廠 預設為內建零依賴定位器(垂直翻轉)傳入 @selkit/floating 的 createFloatingPositioner 即啟用 flip/shift/size 進階定位 */
66
+ positioner?: PositionerFactory;
22
67
  /** 自訂已選顯示內容(tag 或單值) 回傳字串走 textContent 防 XSS 需 markup(icon 等)請回傳 Node */
23
68
  templateSelection?: (option: SelkitOption<T>, meta: {
24
69
  index: number;
@@ -67,35 +112,4 @@ declare class SelkitDom<T> implements SelkitDomInstance<T> {
67
112
  /** 在指定元素或 selector 對應的元素內建立並掛載一個 Selkit 下拉 */
68
113
  declare function createSelkitDom<T = unknown>(host: HTMLElement | string, config?: SelkitDomConfig<T>): SelkitDomInstance<T>;
69
114
 
70
- /**
71
- * @selkit/dom — 預設輕量定位器(零依賴)
72
- *
73
- * 計算邏輯與 DOM 套用分離:computePosition 為純函式(可單元測)
74
- * attachPositioner 負責讀取 rect、套 style、監聽 scroll/resize
75
- */
76
- type Placement = 'bottom' | 'top';
77
- interface Rect {
78
- top: number;
79
- bottom: number;
80
- left: number;
81
- width: number;
82
- }
83
- interface PositionResult {
84
- placement: Placement;
85
- top: number;
86
- left: number;
87
- width: number;
88
- }
89
- /**
90
- * 依觸發元件位置與下拉高度 決定放上方或下方(空間不足才翻轉)
91
- * 並回傳套用座標 不做水平翻轉(select 下拉慣例對齊左緣、同寬)
92
- */
93
- declare function computePosition(triggerRect: Rect, dropdownHeight: number, viewportHeight: number, gap?: number): PositionResult;
94
- interface Positioner {
95
- update(): void;
96
- destroy(): void;
97
- }
98
- /** 將 dropdown 定位到 trigger 旁 並隨 scroll/resize 更新 */
99
- declare function attachPositioner(trigger: HTMLElement, dropdown: HTMLElement, autoWidth?: boolean): Positioner;
100
-
101
- export { type Placement, type PositionResult, type Positioner, type Rect, SelkitDom as Selkit, SelkitDom, type SelkitDomConfig, type SelkitDomInstance, attachPositioner, computePosition, createSelkitDom, createSelkitDom as sk };
115
+ export { type Placement, type PositionResult, type Positioner, type PositionerFactory, type PositionerOptions, type Rect, SelkitDom as Selkit, SelkitDom, type SelkitDomConfig, type SelkitDomInstance, attachPositioner, computePosition, createSelkitDom, createSelkitDom as sk };
package/dist/index.js CHANGED
@@ -49,6 +49,7 @@ var LOAD_MORE_THRESHOLD = 32;
49
49
  var DEFAULT_ITEM_HEIGHT = 36;
50
50
  var DEFAULT_GROUP_HEIGHT = 28;
51
51
  var SR_ONLY_CSS = "position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0";
52
+ var builtinPositioner = (trigger, dropdown, opts) => attachPositioner(trigger, dropdown, opts?.autoWidth ?? false);
52
53
  function resolveParent(parent) {
53
54
  if (!parent) return null;
54
55
  if (typeof parent !== "string") return parent;
@@ -130,6 +131,7 @@ var SelkitDom = class {
130
131
  #itemHeight;
131
132
  #groupHeight;
132
133
  #dropdownParent;
134
+ #positionerFactory;
133
135
  #templateSelection;
134
136
  #templateOption;
135
137
  #templateArrow;
@@ -175,6 +177,7 @@ var SelkitDom = class {
175
177
  this.#itemHeight = cfg.itemHeight ?? DEFAULT_ITEM_HEIGHT;
176
178
  this.#groupHeight = cfg.groupHeight ?? DEFAULT_GROUP_HEIGHT;
177
179
  this.#dropdownParent = resolveParent(cfg.dropdownParent);
180
+ this.#positionerFactory = cfg.positioner ?? builtinPositioner;
178
181
  this.#templateSelection = cfg.templateSelection;
179
182
  this.#templateOption = cfg.templateOption;
180
183
  this.#templateArrow = cfg.templateArrow;
@@ -715,11 +718,9 @@ var SelkitDom = class {
715
718
  this.#dropdown.hidden = false;
716
719
  if (this.#positioner) this.#positioner.update();
717
720
  else
718
- this.#positioner = attachPositioner(
719
- this.#control,
720
- this.#dropdown,
721
- this.#dropdownAutoWidth
722
- );
721
+ this.#positioner = this.#positionerFactory(this.#control, this.#dropdown, {
722
+ autoWidth: this.#dropdownAutoWidth
723
+ });
723
724
  } else {
724
725
  this.#dropdown.hidden = true;
725
726
  this.#positioner?.destroy();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selkit/dom",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Vanilla JS renderer for Selkit — DOM, events, a11y and default positioner.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "sideEffects": false,
21
21
  "dependencies": {
22
- "@selkit/core": "0.4.0"
22
+ "@selkit/core": "0.6.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "axe-core": "^4.12.1",