@vanilla-bean/components 1.0.2 → 1.1.1

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 (43) hide show
  1. package/Component/Component.js +5 -5
  2. package/Component/Component.scenarios.js +2 -2
  3. package/Component/Component.test.js +2 -2
  4. package/Component/observeElementConnection.js +1 -1
  5. package/README.md +1 -1
  6. package/components/BottomSheet/README.md +1 -1
  7. package/components/Button/Button.lld.md +1 -1
  8. package/components/Code/Code.lld.md +1 -1
  9. package/components/ColorPicker/ColorPicker.js +1 -1
  10. package/components/Dialog/Dialog.js +1 -1
  11. package/components/Dialog/Dialog.lld.md +1 -1
  12. package/components/Dialog/README.md +10 -10
  13. package/components/Form/Form.js +9 -9
  14. package/components/Form/Form.lld.md +2 -2
  15. package/components/Form/README.md +3 -3
  16. package/components/Input/README.md +7 -7
  17. package/components/Keyboard/Keyboard.lld.md +1 -1
  18. package/components/Menu/Menu.js +3 -3
  19. package/components/Notify/Notify.lld.md +2 -2
  20. package/components/Page/Page.lld.md +1 -1
  21. package/components/RadioButton/RadioButton.lld.md +1 -1
  22. package/components/Router/README.md +12 -12
  23. package/components/Select/README.md +5 -5
  24. package/components/Select/Select.js +1 -1
  25. package/components/Table/README.md +4 -4
  26. package/components/Table/Table.lld.md +1 -1
  27. package/components/TagList/TagList.lld.md +1 -1
  28. package/components/TooltipWrapper/TooltipWrapper.lld.md +2 -2
  29. package/components/Whiteboard/Whiteboard.lld.md +1 -1
  30. package/index.d.ts +4 -3
  31. package/package.json +1 -1
  32. package/theme/.test.js +20 -4
  33. package/theme/README.md +15 -8
  34. package/theme/button.js +1 -1
  35. package/theme/colors.js +9 -2
  36. package/theme/input.js +3 -3
  37. package/theme/page.js +6 -0
  38. package/theme/scrollbar.js +7 -3
  39. package/theme/table.js +2 -2
  40. package/utils/browser.js +1 -1
  41. package/Component/README.md +0 -455
  42. package/Elem/README.md +0 -373
  43. package/styled/README.md +0 -329
package/Elem/README.md DELETED
@@ -1,373 +0,0 @@
1
- # Elem
2
-
3
- Enhanced DOM element wrapper providing fluent API methods while maintaining direct access to the underlying HTMLElement.
4
-
5
- ## Basic Usage
6
-
7
- ### Simple Element Creation
8
-
9
- Create DOM elements with enhanced manipulation capabilities:
10
-
11
- ```js
12
- import { Elem } from '@vanilla-bean/components';
13
-
14
- const button = new Elem({
15
- tag: 'button',
16
- textContent: 'Click me',
17
- className: 'btn btn-primary',
18
- onclick: () => alert('Clicked!'),
19
- appendTo: document.body,
20
- });
21
- ```
22
-
23
- ### Complex Nested Structures
24
-
25
- Build complex DOM hierarchies with nested elements:
26
-
27
- ```js
28
- const card = new Elem(
29
- {
30
- tag: 'div',
31
- className: 'card',
32
- style: { padding: '20px', margin: '10px' },
33
- },
34
- new Elem({ tag: 'h3', textContent: 'Card Title' }),
35
- new Elem({ tag: 'p', textContent: 'Card content goes here.' }),
36
- );
37
- ```
38
-
39
- ### Method Chaining
40
-
41
- Chain methods for fluent DOM construction:
42
-
43
- ```js
44
- const navigation = new Elem({ tag: 'nav' })
45
- .addClass('menu', 'horizontal')
46
- .setStyle({ display: 'flex', gap: '16px' })
47
- .append(
48
- new Elem({ tag: 'a', textContent: 'Home', href: '/' }),
49
- new Elem({ tag: 'a', textContent: 'About', href: '/about' }),
50
- new Elem({ tag: 'a', textContent: 'Contact', href: '/contact' }),
51
- )
52
- .appendTo(document.body);
53
- ```
54
-
55
- ### Direct DOM Access
56
-
57
- Access the full HTMLElement API when needed:
58
-
59
- ```js
60
- const input = new Elem({ tag: 'input', type: 'text' });
61
-
62
- // Enhanced methods
63
- input.addClass('form-control').setStyle({ width: '100%' });
64
-
65
- // Direct DOM access
66
- input.elem.focus();
67
- input.elem.select();
68
- input.elem.scrollIntoView({ behavior: 'smooth' });
69
- ```
70
-
71
- ## Configuration Options
72
-
73
- ### Constructor Syntax
74
-
75
- ```js
76
- new Elem(options?, ...children)
77
- ```
78
-
79
- **Parameters:**
80
-
81
- - `options` (Object) - Configuration options and HTML properties
82
- - `children` (...Elem|HTMLElement|string) - Child elements or text content
83
-
84
- ### Core Options
85
-
86
- | Option | Type | Description |
87
- | ------------ | --------------------------- | ---------------------------------- |
88
- | `tag` | `string` | HTML tag name (default: 'div') |
89
- | `style` | `object` | CSS properties as key-value pairs |
90
- | `attributes` | `object` | HTML attributes as key-value pairs |
91
- | `content` | `string\|Elem\|HTMLElement` | Element content |
92
- | `appendTo` | `Elem\|HTMLElement` | Parent element to append to |
93
- | `prependTo` | `Elem\|HTMLElement` | Parent element to prepend to |
94
- | `append` | `Array` | Child elements to append |
95
- | `prepend` | `Array` | Child elements to prepend |
96
-
97
- ### HTML Properties
98
-
99
- All standard HTMLElement properties work as options:
100
-
101
- ```js
102
- new Elem({
103
- // Content properties
104
- textContent: 'Button text',
105
- innerHTML: '<span>HTML content</span>',
106
-
107
- // Form properties
108
- value: 'input value',
109
- checked: true,
110
- disabled: false,
111
-
112
- // Element properties
113
- id: 'unique-id',
114
- className: 'btn primary',
115
- title: 'Tooltip text',
116
-
117
- // Link properties
118
- href: 'https://example.com',
119
- target: '_blank',
120
-
121
- // Image properties
122
- src: 'image.jpg',
123
- alt: 'Image description',
124
- });
125
- ```
126
-
127
- ### Event Handler Properties
128
-
129
- Event handlers can be assigned directly:
130
-
131
- ```js
132
- new Elem({
133
- tag: 'button',
134
- onclick: event => console.log('clicked'),
135
- onmouseover: event => console.log('hover'),
136
- onchange: event => console.log('changed'),
137
- onfocus: event => console.log('focused'),
138
- });
139
- ```
140
-
141
- ## DOM Manipulation
142
-
143
- ### Content Management
144
-
145
- ```js
146
- // Set content (replaces existing)
147
- elem.content('New text content');
148
- elem.content(new Elem({ tag: 'span', textContent: 'HTML element' }));
149
-
150
- // Clear all content
151
- elem.empty();
152
- ```
153
-
154
- ### Child Element Management
155
-
156
- ```js
157
- // Add children
158
- elem.append(child1, child2, 'text content');
159
- elem.prepend(child1, child2);
160
-
161
- // Access children
162
- const childElements = elem.children; // Array of Elem instances
163
- const nativeChildren = elem.elem.children; // HTMLCollection
164
- ```
165
-
166
- ### Hierarchy Management
167
-
168
- ```js
169
- // Add to DOM
170
- elem.appendTo(document.body);
171
- elem.prependTo(document.querySelector('.container'));
172
-
173
- // Navigate hierarchy
174
- const parentElem = elem.parent; // Parent Elem instance (if exists)
175
- const nativeParent = elem.parentElem; // Parent HTMLElement
176
- ```
177
-
178
- ### Style and Attribute Management
179
-
180
- ```js
181
- // Set multiple styles
182
- elem.setStyle({
183
- color: 'red',
184
- fontSize: '16px',
185
- backgroundColor: '#f0f0f0',
186
- });
187
-
188
- // Set multiple attributes
189
- elem.setAttributes({
190
- 'data-id': '123',
191
- 'aria-label': 'Close button',
192
- role: 'button',
193
- });
194
- ```
195
-
196
- ## Class Management
197
-
198
- ### Enhanced Class Operations
199
-
200
- Elem provides enhanced class manipulation with regular expression support:
201
-
202
- ```js
203
- // Check for classes
204
- elem.hasClass('active'); // Check single class
205
- elem.hasClass('btn', 'primary'); // Check multiple classes
206
- elem.hasClass(/^btn-/); // Check with regex pattern
207
-
208
- // Add classes
209
- elem.addClass('new-class');
210
- elem.addClass('class1', 'class2', 'class3');
211
-
212
- // Remove classes
213
- elem.removeClass('old-class');
214
- elem.removeClass(/^temp-/); // Remove all classes starting with 'temp-'
215
- elem.removeClass(/\bmobile-\w+/g); // Remove classes matching pattern
216
-
217
- // Toggle class based on a condition (add when true, remove when false)
218
- elem.toggleClass('active', isActive);
219
- ```
220
-
221
- ### Class Manipulation Examples
222
-
223
- ```js
224
- const button = new Elem({ tag: 'button', className: 'btn btn-primary temp-123' });
225
-
226
- // Remove all temporary classes
227
- button.removeClass(/^temp-/);
228
-
229
- // Add state classes
230
- button.addClass('btn-large', 'btn-rounded');
231
-
232
- // Conditional classes
233
- if (isActive) {
234
- button.addClass('active', 'selected');
235
- }
236
-
237
- // Check for button variants
238
- if (button.hasClass(/^btn-(primary|secondary|danger)$/)) {
239
- console.log('Has button variant class');
240
- }
241
- ```
242
-
243
- ## Event Handling
244
-
245
- ### EventTarget Integration
246
-
247
- Elem extends EventTarget, providing full event capabilities:
248
-
249
- ```js
250
- const button = new Elem({ tag: 'button', textContent: 'Click me' });
251
-
252
- // Option-based event handlers
253
- new Elem({
254
- tag: 'input',
255
- onchange: event => console.log('Value changed:', event.target.value),
256
- onfocus: event => event.target.select(),
257
- });
258
-
259
- // addEventListener method
260
- button.addEventListener('click', event => {
261
- console.log('Button clicked');
262
- });
263
-
264
- // Custom events
265
- button.addEventListener('customEvent', event => {
266
- console.log('Custom event data:', event.detail);
267
- });
268
-
269
- // Dispatch events
270
- button.dispatchEvent(
271
- new CustomEvent('customEvent', {
272
- detail: { message: 'Hello' },
273
- }),
274
- );
275
- ```
276
-
277
- ### Event Handler Options vs Methods
278
-
279
- ```js
280
- // Via constructor options (preferred for initial setup)
281
- const elem = new Elem({
282
- tag: 'button',
283
- onclick: handleClick,
284
- onmouseover: handleHover,
285
- });
286
-
287
- // Via addEventListener (preferred for dynamic binding)
288
- elem.addEventListener('click', handleClick);
289
- elem.addEventListener('mouseover', handleHover);
290
-
291
- // Via native element
292
- elem.elem.addEventListener('click', handleClick);
293
- ```
294
-
295
- ## API Reference
296
-
297
- ### Constructor
298
-
299
- ```js
300
- new Elem(options?, ...children)
301
- ```
302
-
303
- ### Core Methods
304
-
305
- #### Content Methods
306
-
307
- ```js
308
- elem.content(content); // Set element content
309
- elem.empty(); // Remove all child elements
310
- ```
311
-
312
- #### Child Management Methods
313
-
314
- ```js
315
- elem.append(...children); // Append child elements
316
- elem.prepend(...children); // Prepend child elements
317
- elem.appendTo(parent); // Append to parent element
318
- elem.prependTo(parent); // Prepend to parent element
319
- ```
320
-
321
- #### Style and Attribute Methods
322
-
323
- ```js
324
- elem.setStyle(styles); // Set CSS properties
325
- elem.setAttributes(attributes); // Set HTML attributes
326
- elem.setOptions(options); // Set multiple options at once
327
- ```
328
-
329
- #### Class Methods
330
-
331
- ```js
332
- elem.hasClass(...classes); // Check for classes (supports regex)
333
- elem.addClass(...classes); // Add CSS classes
334
- elem.removeClass(...classes); // Remove CSS classes (supports regex)
335
- elem.toggleClass(className, condition); // Add when condition is true, remove when false
336
- ```
337
-
338
- ### Properties
339
-
340
- ```js
341
- elem.elem; // Underlying HTMLElement
342
- elem.parent; // Parent Elem instance (if created by Elem)
343
- elem.parentElem; // Parent HTMLElement
344
- elem.children; // Array of child Elem instances
345
- elem.options; // Configuration options object
346
- ```
347
-
348
- ### Utility Methods
349
-
350
- ```js
351
- elem.toString(); // Returns '[object Elem]'
352
- ```
353
-
354
- ## Integration with Component
355
-
356
- Elem serves as the foundation for the Component class:
357
-
358
- ```js
359
- import { Component } from '@vanilla-bean/components';
360
-
361
- // Component extends Elem with reactive options
362
- const component = new Component({
363
- tag: 'div',
364
- textContent: 'I am reactive!',
365
- });
366
-
367
- // All Elem methods available
368
- component.addClass('component-class');
369
- component.setStyle({ padding: '16px' });
370
-
371
- // Plus Component-specific features
372
- component.options.textContent = 'Updated reactively!';
373
- ```
package/styled/README.md DELETED
@@ -1,329 +0,0 @@
1
- # styled
2
-
3
- Create Component subclasses with scoped CSS: each `styled()` call generates a unique class, processes the theme, and injects a `<style>` element into `<head>`.
4
-
5
- ## Basic Usage
6
-
7
- ### Template Literal Syntax
8
-
9
- Create styled components using template literals with theme integration:
10
-
11
- ```js
12
- const StyledIcon = styled.Icon`
13
- background-color: ${({ colors }) => colors.black};
14
- width: 24px;
15
- height: 24px;
16
-
17
- &:before {
18
- ${({ fonts }) => fonts.fontAwesomeSolid}
19
- content: "\f015";
20
- }
21
- `;
22
- ```
23
-
24
- ### Function Syntax with Configuration
25
-
26
- Use function syntax when you need to pass component configuration options:
27
-
28
- ```js
29
- const ConfiguredComponent = styled(
30
- Component,
31
- ({ colors }) => `
32
- background-color: ${colors.black};
33
- color: ${colors.lighter(colors.blue)};
34
- padding: 12px;
35
-
36
- &:hover {
37
- background-color: ${colors.dark(colors.blue)};
38
- }
39
- `,
40
- {
41
- tag: 'section',
42
- role: 'banner',
43
- textContent: 'Default Text',
44
- },
45
- );
46
- ```
47
-
48
- ### Named Component Shortcuts
49
-
50
- All top-level components are available as shorthand methods:
51
-
52
- ```js
53
- const StyledButton = styled.Button`
54
- background-color: ${({ colors }) => colors.green};
55
- border-radius: 8px;
56
- `;
57
-
58
- const StyledInput = styled.Input`
59
- ${({ fonts }) => fonts.kodeMono}
60
- border: 2px solid ${({ colors }) => colors.blue};
61
- `;
62
- ```
63
-
64
- **Note**: Template literal syntax creates components with empty configuration. Use function syntax to pass component options.
65
-
66
- ## Theme Integration
67
-
68
- Style functions receive the complete theme object containing colors, fonts, and component styles:
69
-
70
- ```js
71
- const ThemedComponent = styled.Component`
72
- ${({ button }) => button} /* Apply base button styles */
73
- ${({ fonts }) => fonts.kodeMono}
74
- background: ${({ colors }) => colors.darker(colors.blue)};
75
- color: ${({ colors }) => colors.mostReadable(colors.blue, [colors.white, colors.black])};
76
- `;
77
- ```
78
-
79
- ### Runtime Style Override
80
-
81
- Override or extend styles when creating component instances:
82
-
83
- ```js
84
- const instance = new StyledComponent({
85
- styles: ({ colors }) => ({
86
- backgroundColor: colors.red,
87
- border: `2px solid ${colors.darker(colors.red)}`,
88
- }),
89
- });
90
- ```
91
-
92
- Object-based styles apply as inline styles. Function-based styles generate scoped CSS.
93
-
94
- ## Component Inheritance
95
-
96
- ### Extending Styled Components
97
-
98
- Build component hierarchies by extending existing styled components:
99
-
100
- ```js
101
- const BaseButton = styled.Button`
102
- padding: 8px 16px;
103
- border-radius: 4px;
104
- `;
105
-
106
- const PrimaryButton = styled(BaseButton)`
107
- background: ${({ colors }) => colors.blue};
108
- color: ${({ colors }) => colors.white};
109
- `;
110
- ```
111
-
112
- ### Template Literals with Any Styled Component
113
-
114
- Template literal syntax works with any styled component, including those created with function syntax:
115
-
116
- ```js
117
- const BaseComponent = styled(Component, () => 'color: red;');
118
-
119
- // Extend any styled component with template literals
120
- const ExtendedComponent = styled(BaseComponent)`
121
- background: ${({ colors }) => colors.blue};
122
- padding: 16px;
123
- `;
124
-
125
- // Use in class definitions for custom methods
126
- class MyComponent extends (styled(BaseComponent)`
127
- font-weight: bold;
128
- border-radius: 4px;
129
- `) {
130
- // Add custom methods here
131
- }
132
- ```
133
-
134
- ### Component Functionality Inheritance
135
-
136
- Styled components inherit all functionality from their base component:
137
-
138
- ```js
139
- const StyledInput = styled.Input`
140
- border: 2px solid ${({ colors }) => colors.blue};
141
- `;
142
-
143
- const instance = new StyledInput({
144
- value: 'initial value',
145
- onChange: event => console.log(event.value),
146
- placeholder: 'Enter text...',
147
- });
148
- ```
149
-
150
- ## CSS Processing
151
-
152
- ### Native CSS Nesting
153
-
154
- Styles are injected as written, no transformation, no runtime compilation. VBC requires Chrome 112+, Firefox 117+, and Safari 16.5+, all of which support the `&` nesting syntax natively.
155
-
156
- ```js
157
- const NestedComponent = styled.Component`
158
- padding: 16px;
159
-
160
- & .child {
161
- margin: 8px;
162
-
163
- &:hover {
164
- background: ${({ colors }) => colors.blue};
165
- }
166
- }
167
-
168
- @media (max-width: 768px) {
169
- padding: 8px;
170
- }
171
- `;
172
- ```
173
-
174
- ### Automatic Scoping
175
-
176
- Each styled component receives a unique class identifier to prevent CSS conflicts:
177
-
178
- ```js
179
- const StyledDiv = styled(Component, () => `color: red;`);
180
- const instance = new StyledDiv();
181
-
182
- // Generated CSS: .a1b2c3d4 { color: red; }
183
- // Component class: "a1b2c3d4"
184
- ```
185
-
186
- ### Conditional Styles
187
-
188
- Apply conditional styles using CSS classes and selectors:
189
-
190
- ```js
191
- const ConditionalComponent = styled.Component`
192
- padding: 12px;
193
- background: ${({ colors }) => colors.white};
194
-
195
- &.active {
196
- background: ${({ colors }) => colors.blue};
197
- color: ${({ colors }) => colors.white};
198
- }
199
-
200
- &.disabled {
201
- opacity: 0.5;
202
- pointer-events: none;
203
- }
204
- `;
205
-
206
- const instance = new ConditionalComponent({
207
- addClass: 'active',
208
- textContent: 'Active Button',
209
- });
210
- ```
211
-
212
- ## Performance
213
-
214
- ### Processing Pipeline
215
-
216
- The styled system processes styles through this pipeline:
217
-
218
- 1. **Component Creation** - Generates unique class identifier via `classSafeNanoid()`
219
- 2. **Style Processing** - Converts template literals into theme functions
220
- 3. **Theme Application** - Injects complete theme object into style functions
221
- 4. **CSS Processing** - Processes styles through `shimCSS()` pipeline
222
- 5. **DOM Injection** - Injects final CSS via `appendStyles()`
223
-
224
- ### Load-Time Optimization
225
-
226
- Style processing timing depends on document state:
227
-
228
- | Document State | Behavior |
229
- | ------------------- | ------------------------------------------ |
230
- | Complete | Processes and injects immediately |
231
- | Loading | Queues for batch processing on window load |
232
- | Multiple Components | Batches together for efficiency |
233
-
234
- ```js
235
- // Document loaded - processes immediately
236
- const StyledComponent = styled(Component, () => 'color: red;');
237
-
238
- // Document loading - queued for batch processing
239
- const AnotherStyled = styled(Component, () => 'color: blue;');
240
- ```
241
-
242
- ## API Reference
243
-
244
- ### styled(BaseComponent, styles?, options?)
245
-
246
- Creates a styled component class.
247
-
248
- **Parameters:**
249
-
250
- - `BaseComponent` (Function) - Component class to extend
251
- - `styles` (Function|String) - Style function or CSS string
252
- - `options` (Object) - Component configuration options
253
-
254
- **Returns:** Extended component class with scoped styling
255
-
256
- ### configured(BaseComponent, options)
257
-
258
- Creates a component with configuration but no styles:
259
-
260
- ```js
261
- const ConfiguredComponent = configured(Component, {
262
- tag: 'article',
263
- role: 'main',
264
- textContent: 'Default Content',
265
- });
266
- ```
267
-
268
- ### Utility Functions
269
-
270
- #### appendStyles(css, id?)
271
-
272
- Inject CSS directly into the page:
273
-
274
- ```js
275
- appendStyles(
276
- `
277
- .my-global-class {
278
- font-weight: bold;
279
- color: red;
280
- }
281
- `,
282
- 'my-global-styles',
283
- );
284
- ```
285
-
286
- #### themeStyles({ styles, scope })
287
-
288
- Generate themed CSS with optional scoping:
289
-
290
- ```js
291
- const themedCSS = themeStyles({
292
- styles: ({ colors }) => `color: ${colors.white}; background: ${colors.black};`,
293
- scope: '.my-component',
294
- });
295
- // Returns: ".my-component { color: hsl(0, 0%, 90%); background: hsl(0, 0%, 10%); }"
296
- ```
297
-
298
- #### shimCSS(styleConfig)
299
-
300
- Complete style processing pipeline:
301
-
302
- ```js
303
- shimCSS({
304
- styles: ({ colors }) => `
305
- display: flex;
306
- background: ${colors.blue};
307
- & .item { padding: 8px; }
308
- `,
309
- scope: '.my-scoped-component',
310
- });
311
- ```
312
-
313
- ## Development Features
314
-
315
- ### Debug Class Names
316
-
317
- Development mode adds inheritance-based class names for easier debugging:
318
-
319
- ```js
320
- // Development classes: "a1b2c3 MyCustomComponent Component Elem"
321
- class MyCustomComponent extends Component {}
322
- const StyledCustom = styled(MyCustomComponent, () => 'color: blue;');
323
- ```
324
-
325
- ### Memory Management
326
-
327
- Class-level styles injected by `styled()` persist for the page lifetime. They are scoped to a unique class and do not interfere with other components, but are not removed when instances disconnect.
328
-
329
- Per-instance styles set via the `styles` option on a component instance are cleaned up when that component disconnects from the DOM.