@lingxia/elements 0.5.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 (46) hide show
  1. package/dist/component.d.ts +50 -0
  2. package/dist/component.js +139 -0
  3. package/dist/dom.d.ts +10 -0
  4. package/dist/dom.js +70 -0
  5. package/dist/index.d.ts +9 -0
  6. package/dist/index.js +9 -0
  7. package/dist/input.d.ts +117 -0
  8. package/dist/input.js +699 -0
  9. package/dist/native_component_wrapper_shared.d.ts +74 -0
  10. package/dist/native_component_wrapper_shared.js +193 -0
  11. package/dist/nativecomponent.d.ts +6 -0
  12. package/dist/nativecomponent.js +82 -0
  13. package/dist/navigator.d.ts +83 -0
  14. package/dist/navigator.js +388 -0
  15. package/dist/picker-web.d.ts +2 -0
  16. package/dist/picker-web.js +727 -0
  17. package/dist/picker.d.ts +77 -0
  18. package/dist/picker.js +342 -0
  19. package/dist/platform.d.ts +6 -0
  20. package/dist/platform.js +24 -0
  21. package/dist/text_component_native_attrs.d.ts +53 -0
  22. package/dist/text_component_native_attrs.js +111 -0
  23. package/dist/text_component_shared.d.ts +7 -0
  24. package/dist/text_component_shared.js +148 -0
  25. package/dist/textarea.d.ts +129 -0
  26. package/dist/textarea.js +841 -0
  27. package/dist/types.d.ts +21 -0
  28. package/dist/types.js +1 -0
  29. package/dist/video.d.ts +134 -0
  30. package/dist/video.js +741 -0
  31. package/package.json +39 -0
  32. package/src/component.ts +164 -0
  33. package/src/dom.ts +83 -0
  34. package/src/index.ts +69 -0
  35. package/src/input.ts +799 -0
  36. package/src/native_component_wrapper_shared.ts +243 -0
  37. package/src/nativecomponent.ts +97 -0
  38. package/src/navigator.ts +533 -0
  39. package/src/picker-web.ts +719 -0
  40. package/src/picker.ts +418 -0
  41. package/src/platform.ts +25 -0
  42. package/src/text_component_native_attrs.ts +137 -0
  43. package/src/text_component_shared.ts +147 -0
  44. package/src/textarea.ts +959 -0
  45. package/src/types.ts +20 -0
  46. package/src/video.ts +855 -0
@@ -0,0 +1,147 @@
1
+ export function getPropOrAttr(el: HTMLElement, name: string): unknown {
2
+ const attr = el.getAttribute(name);
3
+ if (attr !== null) return attr;
4
+ const camelName = name.replace(/-([a-z])/g, (_m, ch: string) => ch.toUpperCase());
5
+ const self = el as unknown as Record<string, unknown>;
6
+ if (Object.prototype.hasOwnProperty.call(self, camelName)) {
7
+ const value = self[camelName];
8
+ if (value !== undefined && value !== null) return value;
9
+ }
10
+ return undefined;
11
+ }
12
+
13
+ export function parseNumberLike(value: unknown): number | undefined {
14
+ if (typeof value === "number") {
15
+ return Number.isFinite(value) ? value : undefined;
16
+ }
17
+ if (typeof value === "string") {
18
+ const parsed = Number(value);
19
+ return Number.isFinite(parsed) ? parsed : undefined;
20
+ }
21
+ return undefined;
22
+ }
23
+
24
+ export function getBoolAttr(el: HTMLElement, name: string): boolean {
25
+ const raw = getPropOrAttr(el, name);
26
+ if (raw === undefined || raw === null) return false;
27
+ if (typeof raw === "boolean") return raw;
28
+ const val = String(raw).trim().toLowerCase();
29
+ if (val === "false" || val === "0" || val === "null" || val === "undefined") {
30
+ return false;
31
+ }
32
+ return true;
33
+ }
34
+
35
+ export function getNumAttr(el: HTMLElement, name: string): number | undefined {
36
+ const raw = getPropOrAttr(el, name);
37
+ if (raw === undefined || raw === null) return undefined;
38
+ if (typeof raw === "number") return Number.isFinite(raw) ? raw : undefined;
39
+ const val = String(raw).trim();
40
+ if (val === "") return undefined;
41
+ const n = Number(val);
42
+ return Number.isNaN(n) ? undefined : n;
43
+ }
44
+
45
+ export function shouldRefreshForDataAttribute(name: string): boolean {
46
+ const normalized = name.trim().toLowerCase();
47
+ return normalized.startsWith("data-");
48
+ }
49
+
50
+ function dataAttrToDatasetKey(attr: string): string {
51
+ const raw = attr.slice(5).trim();
52
+ if (!raw) return "";
53
+ const parts = raw.split("-").filter(Boolean);
54
+ if (parts.length === 0) return "";
55
+ return parts
56
+ .map((segment, index) => {
57
+ if (index === 0) return segment.toLowerCase();
58
+ return segment.charAt(0).toUpperCase() + segment.slice(1);
59
+ })
60
+ .join("");
61
+ }
62
+
63
+ export function collectDataset(el: HTMLElement): Record<string, string> {
64
+ const dataset: Record<string, string> = {};
65
+ const attrs = el.getAttributeNames();
66
+ for (const attr of attrs) {
67
+ if (!attr.startsWith("data-")) continue;
68
+ const key = dataAttrToDatasetKey(attr);
69
+ if (!key) continue;
70
+ const value = el.getAttribute(attr);
71
+ if (value == null) continue;
72
+ dataset[key] = value;
73
+ }
74
+ return dataset;
75
+ }
76
+
77
+ function findScrollableAncestor(el: HTMLElement): HTMLElement | null {
78
+ let node: HTMLElement | null = el.parentElement;
79
+ while (node) {
80
+ const style = getComputedStyle(node);
81
+ const overflowY = style.overflowY;
82
+ const scrollable = (overflowY === "auto" || overflowY === "scroll") && node.scrollHeight > node.clientHeight + 1;
83
+ if (scrollable) {
84
+ return node;
85
+ }
86
+ node = node.parentElement;
87
+ }
88
+ return null;
89
+ }
90
+
91
+ function applyScrollDelta(el: HTMLElement, deltaY: number): void {
92
+ if (Math.abs(deltaY) <= 1) return;
93
+ const target = findScrollableAncestor(el);
94
+ if (target) {
95
+ target.scrollTop += Math.round(deltaY);
96
+ return;
97
+ }
98
+ window.scrollBy(0, Math.round(deltaY));
99
+ }
100
+
101
+ export function ensureElementVisibleForKeyboard(
102
+ el: HTMLElement,
103
+ explicitKeyboardHeight = 0,
104
+ forceCenter = false,
105
+ extraDelays: number[] = [120]
106
+ ): void {
107
+ const tryScroll = () => {
108
+ if (!el.isConnected) return;
109
+ const rect = el.getBoundingClientRect();
110
+ const layoutViewportHeight = window.innerHeight || document.documentElement.clientHeight || 0;
111
+ const visualViewport = window.visualViewport;
112
+ const visualBottom = visualViewport ? (visualViewport.offsetTop + visualViewport.height) : layoutViewportHeight;
113
+ const keyboardHeight = Math.max(0, explicitKeyboardHeight || 0);
114
+ const keyboardLikelyVisible =
115
+ keyboardHeight > 0 ||
116
+ (!!visualViewport && visualViewport.height < (layoutViewportHeight - 40));
117
+ if (!keyboardLikelyVisible) {
118
+ return;
119
+ }
120
+ const viewportHeight = keyboardHeight > 0
121
+ ? Math.min(layoutViewportHeight, layoutViewportHeight - keyboardHeight)
122
+ : Math.min(layoutViewportHeight, visualBottom);
123
+ if (viewportHeight <= 0) return;
124
+ const topSafe = 12;
125
+ const bottomSafe = 24;
126
+ let delta = 0;
127
+ const visibleBottom = Math.max(topSafe, viewportHeight - bottomSafe);
128
+ if (rect.bottom > visibleBottom) {
129
+ delta = rect.bottom - visibleBottom;
130
+ } else if (rect.top < topSafe) {
131
+ delta = rect.top - topSafe;
132
+ }
133
+ if (Math.abs(delta) > 1) {
134
+ applyScrollDelta(el, delta);
135
+ return;
136
+ }
137
+ if (forceCenter && rect.bottom > layoutViewportHeight * 0.6) {
138
+ el.scrollIntoView({ block: "center", inline: "nearest", behavior: "auto" });
139
+ }
140
+ };
141
+
142
+ tryScroll();
143
+ requestAnimationFrame(() => tryScroll());
144
+ extraDelays.forEach((delay) => {
145
+ setTimeout(() => tryScroll(), delay);
146
+ });
147
+ }