@vanilla-bean/components 1.0.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 (147) hide show
  1. package/Component/Component.js +598 -0
  2. package/Component/Component.scenarios.js +88 -0
  3. package/Component/Component.test.js +717 -0
  4. package/Component/README.md +455 -0
  5. package/Component/index.js +3 -0
  6. package/Component/observeElementConnection.js +52 -0
  7. package/Component/observeElementConnection.test.js +121 -0
  8. package/Elem/Elem.js +304 -0
  9. package/Elem/Elem.test.js +679 -0
  10. package/Elem/README.md +373 -0
  11. package/Elem/index.js +1 -0
  12. package/FontWithASyntaxHighlighter-Regular.woff2 +0 -0
  13. package/LICENSE +21 -0
  14. package/README.md +413 -0
  15. package/components/BottomSheet/BottomSheet.js +192 -0
  16. package/components/BottomSheet/BottomSheet.lld.md +25 -0
  17. package/components/BottomSheet/README.md +66 -0
  18. package/components/BottomSheet/index.js +1 -0
  19. package/components/Button/Button.js +53 -0
  20. package/components/Button/Button.lld.md +21 -0
  21. package/components/Button/index.js +1 -0
  22. package/components/Calendar/Calendar.js +720 -0
  23. package/components/Calendar/Calendar.lld.md +22 -0
  24. package/components/Calendar/CalendarEvent.js +102 -0
  25. package/components/Calendar/Toolbar.js +78 -0
  26. package/components/Calendar/index.js +2 -0
  27. package/components/Calendar/utils.js +56 -0
  28. package/components/Code/Code.js +84 -0
  29. package/components/Code/Code.lld.md +21 -0
  30. package/components/Code/index.js +1 -0
  31. package/components/ColorPicker/ColorPicker.js +445 -0
  32. package/components/ColorPicker/ColorPicker.lld.md +21 -0
  33. package/components/ColorPicker/index.js +1 -0
  34. package/components/ColorPicker/svg.js +5 -0
  35. package/components/Dialog/Dialog.js +278 -0
  36. package/components/Dialog/Dialog.lld.md +20 -0
  37. package/components/Dialog/README.md +96 -0
  38. package/components/Dialog/index.js +1 -0
  39. package/components/Form/Form.js +257 -0
  40. package/components/Form/Form.lld.md +21 -0
  41. package/components/Form/README.md +87 -0
  42. package/components/Form/index.js +1 -0
  43. package/components/Icon/Icon.js +54 -0
  44. package/components/Icon/Icon.lld.md +21 -0
  45. package/components/Icon/index.js +1 -0
  46. package/components/Input/Input.js +173 -0
  47. package/components/Input/Input.lld.md +28 -0
  48. package/components/Input/README.md +97 -0
  49. package/components/Input/index.js +2 -0
  50. package/components/Input/utils.js +122 -0
  51. package/components/Keyboard/Key.js +38 -0
  52. package/components/Keyboard/Keyboard.js +173 -0
  53. package/components/Keyboard/Keyboard.lld.md +21 -0
  54. package/components/Keyboard/index.js +1 -0
  55. package/components/Label/Label.js +214 -0
  56. package/components/Label/Label.lld.md +20 -0
  57. package/components/Label/index.js +1 -0
  58. package/components/Link/Link.js +43 -0
  59. package/components/Link/Link.lld.md +15 -0
  60. package/components/Link/index.js +1 -0
  61. package/components/List/List.js +82 -0
  62. package/components/List/List.lld.md +19 -0
  63. package/components/List/index.js +1 -0
  64. package/components/Menu/Menu.js +93 -0
  65. package/components/Menu/Menu.lld.md +15 -0
  66. package/components/Menu/index.js +1 -0
  67. package/components/Notify/Notify.js +96 -0
  68. package/components/Notify/Notify.lld.md +20 -0
  69. package/components/Notify/index.js +1 -0
  70. package/components/Page/Page.js +67 -0
  71. package/components/Page/Page.lld.md +20 -0
  72. package/components/Page/index.js +1 -0
  73. package/components/Popover/Popover.js +175 -0
  74. package/components/Popover/Popover.lld.md +19 -0
  75. package/components/Popover/index.js +1 -0
  76. package/components/RadioButton/RadioButton.js +108 -0
  77. package/components/RadioButton/RadioButton.lld.md +15 -0
  78. package/components/RadioButton/index.js +1 -0
  79. package/components/Router/README.md +160 -0
  80. package/components/Router/Router.js +150 -0
  81. package/components/Router/Router.lld.md +31 -0
  82. package/components/Router/View.js +15 -0
  83. package/components/Router/index.js +2 -0
  84. package/components/Router/utils.js +17 -0
  85. package/components/Select/README.md +88 -0
  86. package/components/Select/Select.js +74 -0
  87. package/components/Select/Select.lld.md +20 -0
  88. package/components/Select/index.js +1 -0
  89. package/components/Table/README.md +94 -0
  90. package/components/Table/Table.js +171 -0
  91. package/components/Table/Table.lld.md +21 -0
  92. package/components/Table/index.js +1 -0
  93. package/components/TagList/Tag.js +84 -0
  94. package/components/TagList/TagList.js +118 -0
  95. package/components/TagList/TagList.lld.md +30 -0
  96. package/components/TagList/design.excalidraw.png +0 -0
  97. package/components/TagList/index.js +2 -0
  98. package/components/Tooltip/Tooltip.js +139 -0
  99. package/components/Tooltip/Tooltip.lld.md +22 -0
  100. package/components/Tooltip/index.js +1 -0
  101. package/components/TooltipWrapper/TooltipWrapper.js +89 -0
  102. package/components/TooltipWrapper/TooltipWrapper.lld.md +21 -0
  103. package/components/TooltipWrapper/index.js +1 -0
  104. package/components/Whiteboard/Whiteboard.js +198 -0
  105. package/components/Whiteboard/Whiteboard.lld.md +35 -0
  106. package/components/Whiteboard/index.js +1 -0
  107. package/components/index.js +27 -0
  108. package/eslint.config.cjs +118 -0
  109. package/index.d.ts +635 -0
  110. package/index.js +19 -0
  111. package/package.json +123 -0
  112. package/plugins/asText.js +38 -0
  113. package/plugins/loadPlugins.js +5 -0
  114. package/plugins/markdownLoader.js +121 -0
  115. package/prettier.config.cjs +7 -0
  116. package/spellcheck.config.cjs +227 -0
  117. package/styled/README.md +329 -0
  118. package/styled/appendStyles.js +26 -0
  119. package/styled/appendStyles.test.js +45 -0
  120. package/styled/index.js +4 -0
  121. package/styled/shimCSS.js +31 -0
  122. package/styled/shimCSS.test.js +103 -0
  123. package/styled/styled.js +91 -0
  124. package/styled/styled.test.js +586 -0
  125. package/styled/themeStyles.js +36 -0
  126. package/styled/themeStyles.test.js +135 -0
  127. package/test-setup.js +123 -0
  128. package/theme/.test.js +69 -0
  129. package/theme/README.md +607 -0
  130. package/theme/button.js +100 -0
  131. package/theme/code.js +123 -0
  132. package/theme/colors.js +42 -0
  133. package/theme/fonts.js +42 -0
  134. package/theme/index.js +33 -0
  135. package/theme/input.js +64 -0
  136. package/theme/page.js +208 -0
  137. package/theme/scrollbar.js +24 -0
  138. package/theme/table.js +53 -0
  139. package/utils/README.md +176 -0
  140. package/utils/browser.js +92 -0
  141. package/utils/class.js +30 -0
  142. package/utils/color.js +81 -0
  143. package/utils/data.js +164 -0
  144. package/utils/element.js +55 -0
  145. package/utils/index.js +7 -0
  146. package/utils/rand.js +12 -0
  147. package/utils/string.js +72 -0
package/Elem/Elem.js ADDED
@@ -0,0 +1,304 @@
1
+ import { buildClassList } from '../utils';
2
+
3
+ /** Elem - A bare-bones general purpose element building block */
4
+ class Elem extends EventTarget {
5
+ /**
6
+ * Create an Element wrapper with enhanced DOM manipulation
7
+ * @param {object} [options] - Element configuration
8
+ * @param {string} [options.tag] - HTML tag name
9
+ * @param {object} [options.style] - CSS properties as key-value pairs
10
+ * @param {object} [options.attributes] - HTML attributes as key-value pairs
11
+ * @param {string} [options.className] - CSS class names
12
+ * @param {string} [options.id] - Element ID
13
+ * @param {string} [options.textContent] - Element text content
14
+ * @param {string} [options.innerText] - Element visible text content
15
+ * @param {string} [options.innerHTML] - Element HTML content
16
+ * @param {string|Elem|HTMLElement} [options.content] - Element content (text or elements)
17
+ * @param {Elem|HTMLElement} [options.appendTo] - Parent element to append to
18
+ * @param {Elem|HTMLElement} [options.prependTo] - Parent element to prepend to
19
+ * @param {Array<Elem|HTMLElement>} [options.append] - Child elements to append
20
+ * @param {Array<Elem|HTMLElement>} [options.prepend] - Child elements to prepend
21
+ * @param {HTMLElement} [options.before] - Insert before this element
22
+ * @param {boolean} [options.disabled] - Disable form element
23
+ * @param {Function} [options.onclick] - Click event handler
24
+ * @param {...(Elem|HTMLElement|string)} children - Elements to append
25
+ * @example
26
+ * new Elem({ tag: 'button', textContent: 'Click me', onclick: () => alert('clicked') })
27
+ */
28
+ constructor({ tag = 'div', ...optionsWithoutConfig } = {}, ...children) {
29
+ super();
30
+
31
+ this.tag = tag;
32
+ this.elem = document.createElement(tag);
33
+ this.options = {
34
+ ...optionsWithoutConfig,
35
+ ...(children.length > 0 ? { append: [optionsWithoutConfig.append, ...children] } : {}),
36
+ };
37
+
38
+ this.elem._elem = this;
39
+
40
+ Object.entries(this.options).forEach(([key, value]) => this._setOption(key, value));
41
+ }
42
+
43
+ /**
44
+ * String representation of Elem instance
45
+ * @returns {string} '[object Elem]'
46
+ */
47
+ toString() {
48
+ return '[object Elem]';
49
+ }
50
+
51
+ /**
52
+ * Handles option assignment by routing to appropriate method or property
53
+ * @param {string} key - Option property name
54
+ * @param {any} value - Option value to assign
55
+ * @private
56
+ */
57
+ _setOption(key, value) {
58
+ if (key === 'style') this.setStyle(value);
59
+ else if (key === 'attributes') this.setAttributes(value);
60
+ else if (key === 'before') {
61
+ const target = value?.elem ?? value;
62
+ target?.before(this.elem);
63
+ } else if (typeof this[key] === 'function') this[key].call(this, value);
64
+ else if (typeof this.elem[key] === 'function') {
65
+ if (value?.elem) value = value.elem;
66
+
67
+ this.elem[key].call(this.elem, value);
68
+ } else this.elem[key] = value;
69
+ }
70
+
71
+ /**
72
+ * Get parent HTMLElement
73
+ * @returns {HTMLElement|null} Parent element
74
+ */
75
+ get parentElem() {
76
+ return this.elem?.parentElement;
77
+ }
78
+
79
+ /**
80
+ * Get parent Elem instance
81
+ * @returns {Elem|undefined} Parent Elem instance if exists
82
+ */
83
+ get parent() {
84
+ return this.parentElem?._elem;
85
+ }
86
+
87
+ /**
88
+ * Get child Elem instances
89
+ * @returns {Array<Elem>} Array of child Elem instances
90
+ */
91
+ get children() {
92
+ return Array.from(this.elem.children).flatMap(({ _elem }) => (_elem ? [_elem] : []));
93
+ }
94
+
95
+ /**
96
+ * Batch update options
97
+ * @param {object} options - Options to set
98
+ * @returns {Elem} This instance for chaining
99
+ */
100
+ setOptions(options) {
101
+ Object.entries(options).forEach(([name, value]) => (this.options[name] = value));
102
+
103
+ return this;
104
+ }
105
+
106
+ /**
107
+ * Check if element has specified classes (supports regex patterns)
108
+ * @param {...(string|RegExp)} classes - Class names or regex patterns to check
109
+ * @returns {boolean} True if all classes are present
110
+ * @example
111
+ * elem.hasClass('active', 'visible')
112
+ * elem.hasClass(/^btn-/, 'active')
113
+ */
114
+ hasClass(...classes) {
115
+ return classes.flat(Number.POSITIVE_INFINITY).every(className => {
116
+ if (className instanceof RegExp) return className.test(this.elem.className);
117
+
118
+ const escaped = className.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
119
+ return new RegExp(`\\b${escaped}\\b`, 'g').test(this.elem.className);
120
+ });
121
+ }
122
+
123
+ /**
124
+ * Add CSS classes to element
125
+ * @param {...(string|Array<string>)} classes - Class names to add
126
+ * @returns {Elem} This instance for chaining
127
+ * @example
128
+ * elem.addClass('active', 'visible')
129
+ * elem.addClass(['btn', 'btn-primary'])
130
+ */
131
+ addClass(...classes) {
132
+ this.elem.classList.add(...buildClassList(classes));
133
+
134
+ return this;
135
+ }
136
+
137
+ /**
138
+ * Remove CSS classes from element (supports regex patterns)
139
+ * @param {...(string|RegExp)} classes - Class names or regex patterns to remove
140
+ * @returns {Elem} This instance for chaining
141
+ * @example
142
+ * elem.removeClass('active', 'hidden')
143
+ * elem.removeClass(/^temp-/)
144
+ */
145
+ removeClass(...classes) {
146
+ classes.flat(Number.POSITIVE_INFINITY).forEach(className => {
147
+ let classRegex;
148
+ if (className instanceof RegExp) {
149
+ classRegex = new RegExp(
150
+ className.source,
151
+ className.flags.includes('g') ? className.flags : className.flags + 'g',
152
+ );
153
+ } else {
154
+ const escaped = className.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
155
+ classRegex = new RegExp(`\\b${escaped}\\b`, 'g');
156
+ }
157
+
158
+ if (classRegex.test(this.elem.className)) {
159
+ this.elem.className = this.elem.className.replaceAll(classRegex, '');
160
+ }
161
+ });
162
+
163
+ return this;
164
+ }
165
+
166
+ /**
167
+ * Toggle a CSS class based on a condition.
168
+ * @param {string} name - Class name to toggle
169
+ * @param {boolean} condition - Add class when true, remove when false
170
+ * @returns {Elem} This instance for chaining
171
+ * @example
172
+ * elem.toggleClass('active', isActive)
173
+ */
174
+ toggleClass(name, condition) {
175
+ if (condition) this.addClass(name);
176
+ else this.removeClass(name);
177
+ return this;
178
+ }
179
+
180
+ /**
181
+ * Remove all child elements
182
+ * @returns {void}
183
+ */
184
+ empty() {
185
+ this.elem.replaceChildren();
186
+ return this;
187
+ }
188
+
189
+ /**
190
+ * Apply CSS styles to element
191
+ * @param {object} style - CSS properties as key-value pairs
192
+ * @returns {Elem} This instance for chaining
193
+ * @example
194
+ * elem.setStyle({ color: 'red', fontSize: '16px' })
195
+ */
196
+ setStyle(style) {
197
+ if (!style || typeof style !== 'object' || Array.isArray(style)) return this;
198
+
199
+ Object.entries(style).forEach(([key, value]) => {
200
+ if (!key || /^\d+$/.test(key)) return;
201
+
202
+ this.elem.style[key] = value;
203
+ });
204
+
205
+ return this;
206
+ }
207
+
208
+ /**
209
+ * Set HTML attributes on element
210
+ * @param {object} attributes - Attributes as key-value pairs
211
+ * @returns {Elem} This instance for chaining
212
+ * @example
213
+ * elem.setAttributes({ 'data-id': '123', role: 'button' })
214
+ */
215
+ setAttributes(attributes) {
216
+ Object.entries(attributes).forEach(([key, value]) => this.elem.setAttribute(key, value));
217
+
218
+ return this;
219
+ }
220
+
221
+ /**
222
+ * Set element content (text or elements)
223
+ * @param {string|Elem|HTMLElement} content - Content to set
224
+ * @returns {Elem} This instance for chaining
225
+ * @example
226
+ * elem.content('Hello world')
227
+ * elem.content(new Elem({ tag: 'span', textContent: 'Child' }))
228
+ */
229
+ content(content) {
230
+ if (typeof content === 'string') this.elem.textContent = content;
231
+ else {
232
+ this.empty();
233
+ this.append(content);
234
+ }
235
+
236
+ return this;
237
+ }
238
+
239
+ /**
240
+ * Append this element to a parent
241
+ * @param {Elem|HTMLElement} parentElem - Parent element to append to
242
+ * @returns {Elem} This instance for chaining
243
+ */
244
+ appendTo(parentElem) {
245
+ if (parentElem?.append) parentElem.append(this.elem);
246
+
247
+ return this;
248
+ }
249
+
250
+ /**
251
+ * Prepend this element to a parent
252
+ * @param {Elem|HTMLElement} parentElem - Parent element to prepend to
253
+ * @returns {Elem} This instance for chaining
254
+ */
255
+ prependTo(parentElem) {
256
+ if (!parentElem) return this;
257
+ const el = parentElem.elem ?? parentElem;
258
+ if (el.firstChild) el.insertBefore(this.elem, el.firstChild);
259
+ else el.append(this.elem);
260
+
261
+ return this;
262
+ }
263
+
264
+ /**
265
+ * Append child elements to this element
266
+ * @param {...(Elem|HTMLElement)} children - Elements to append
267
+ * @returns {Elem} This instance for chaining
268
+ * @example
269
+ * elem.append(child1, child2, [child3, child4])
270
+ */
271
+ append(...children) {
272
+ [children].flat(Number.POSITIVE_INFINITY).forEach(child => {
273
+ if (!child) return;
274
+
275
+ if (child?.elem) child = child.elem;
276
+
277
+ this.elem.append(child);
278
+ });
279
+
280
+ return this;
281
+ }
282
+
283
+ /**
284
+ * Prepend child elements to this element
285
+ * @param {...(Elem|HTMLElement)} children - Elements to prepend
286
+ * @returns {Elem} This instance for chaining
287
+ * @example
288
+ * elem.prepend(child1, child2, [child3, child4])
289
+ */
290
+ prepend(...children) {
291
+ [children].flat(Number.POSITIVE_INFINITY).forEach(child => {
292
+ if (!child) return;
293
+
294
+ if (child?.elem) child = child.elem;
295
+
296
+ if (this.elem.firstChild) this.elem.insertBefore(child, this.elem.firstChild);
297
+ else this.elem.append(child);
298
+ });
299
+
300
+ return this;
301
+ }
302
+ }
303
+
304
+ export default Elem;