sp-component 0.0.1 → 0.0.2

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 (2) hide show
  1. package/README.md +209 -144
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,12 +1,14 @@
1
1
  # SP Components
2
2
 
3
- A library of **57 Web Components** , compatible with any framework — Angular, React, Vue, Svelte, or plain HTML.
3
+ A library of **58 Web Components**, compatible with any framework — Angular, React, Vue, Svelte, or plain HTML.
4
4
 
5
- - Zero runtime dependencies (only Lit)
6
- - Full TypeScript support
7
- - Form-associated (native `<form>` integration)
8
- - Keyboard navigation & ARIA accessible
9
- - `prefers-reduced-motion` support
5
+ - **Zero extra dependencies** only Lit as peer dependency
6
+ - **Full TypeScript support** — types included
7
+ - **Form-associated** native `<form>` + `FormData` integration
8
+ - **Accessible** — keyboard navigation & ARIA on all interactive components
9
+ - **Dark mode** — automatic via `prefers-color-scheme` with CSS token system
10
+ - **Themeable** — CSS custom properties for colors, spacing and typography
11
+ - **Tree-shakeable** — import only what you need
10
12
 
11
13
  ---
12
14
 
@@ -16,6 +18,9 @@ A library of **57 Web Components** , compatible with any framework — Angular,
16
18
  - [Table of Contents](#table-of-contents)
17
19
  - [Installation](#installation)
18
20
  - [Quick Start](#quick-start)
21
+ - [Dark Mode \& Theming](#dark-mode--theming)
22
+ - [Customize the color palette](#customize-the-color-palette)
23
+ - [Apply your own font](#apply-your-own-font)
19
24
  - [Usage by Framework](#usage-by-framework)
20
25
  - [HTML / Vanilla JS](#html--vanilla-js)
21
26
  - [Angular](#angular)
@@ -26,8 +31,9 @@ A library of **57 Web Components** , compatible with any framework — Angular,
26
31
  - [Buttons \& Actions](#buttons--actions)
27
32
  - [Navigation](#navigation)
28
33
  - [Overlays](#overlays)
29
- - [Display](#display)
30
- - [Customization](#customization)
34
+ - [Data Display](#data-display)
35
+ - [Feedback \& Status](#feedback--status)
36
+ - [Layout \& Utilities](#layout--utilities)
31
37
  - [Events](#events)
32
38
  - [Form Participation](#form-participation)
33
39
  - [Contributing](#contributing)
@@ -38,28 +44,76 @@ A library of **57 Web Components** , compatible with any framework — Angular,
38
44
  ## Installation
39
45
 
40
46
  ```bash
41
- npm install libreria-component
47
+ # npm
48
+ npm install sp-component
49
+
50
+ # yarn
51
+ yarn add sp-component
52
+
53
+ # pnpm
54
+ pnpm add sp-component
42
55
  ```
43
56
 
44
57
  ---
45
58
 
46
59
  ## Quick Start
47
60
 
48
- Import everything at once:
61
+ Import all components at once:
49
62
 
50
63
  ```js
51
- import "libreria-component";
64
+ import "sp-component";
52
65
  ```
53
66
 
54
- Or import only the components you need:
67
+ Or import only what you need (tree-shaking):
55
68
 
56
69
  ```js
57
- import "libreria-component/components/button";
58
- import "libreria-component/components/input";
70
+ import "sp-component/components/button";
71
+ import "sp-component/components/input";
72
+ import "sp-component/components/autocomplete";
59
73
  ```
60
74
 
61
75
  ---
62
76
 
77
+ ## Dark Mode & Theming
78
+
79
+ Import the token file once at the root of your app to enable dark mode and global theming:
80
+
81
+ ```js
82
+ // main.js / main.ts
83
+ import "sp-component";
84
+ import "sp-component/tokens.css";
85
+ ```
86
+
87
+ ```html
88
+ <!-- or via link tag -->
89
+ <link rel="stylesheet" href="node_modules/sp-component/dist/tokens.css" />
90
+ ```
91
+
92
+ The token file defines CSS custom properties for both light and dark mode using `prefers-color-scheme`. Components automatically adapt — no configuration needed.
93
+
94
+ ### Customize the color palette
95
+
96
+ Override any token in your own CSS:
97
+
98
+ ```css
99
+ :root {
100
+ --sp-primary: #6366f1; /* indigo instead of blue */
101
+ --sp-primary-hover: #4f46e5;
102
+ --sp-primary-bg: #eef2ff;
103
+ --sp-primary-focus: rgba(99, 102, 241, 0.2);
104
+ }
105
+ ```
106
+
107
+ ### Apply your own font
108
+
109
+ All components inherit the document font automatically:
110
+
111
+ ```css
112
+ body {
113
+ font-family: "Inter", sans-serif;
114
+ }
115
+ ```
116
+
63
117
  ## Usage by Framework
64
118
 
65
119
  ### HTML / Vanilla JS
@@ -69,21 +123,20 @@ import "libreria-component/components/input";
69
123
  <html>
70
124
  <head>
71
125
  <script type="module">
72
- import "libreria-component";
126
+ import "sp-component";
127
+ import "sp-component/tokens.css";
73
128
  </script>
74
129
  </head>
75
130
  <body>
76
131
  <sp-button variant="primary">Click me</sp-button>
77
132
 
78
- <sp-input
79
- label="Email"
80
- type="email"
81
- placeholder="you@example.com"
82
- ></sp-input>
133
+ <sp-input label="Email" type="email" placeholder="you@example.com"></sp-input>
134
+
135
+ <sp-autocomplete label="Country" placeholder="Search..."></sp-autocomplete>
83
136
 
84
137
  <script>
85
- document.querySelector("sp-button").addEventListener("sp-click", () => {
86
- console.log("clicked!");
138
+ document.querySelector("sp-input").addEventListener("sp-input", (e) => {
139
+ console.log(e.detail.value);
87
140
  });
88
141
  </script>
89
142
  </body>
@@ -99,7 +152,8 @@ Add `CUSTOM_ELEMENTS_SCHEMA` to your module or standalone component:
99
152
  ```ts
100
153
  // app.module.ts
101
154
  import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
102
- import "libreria-component";
155
+ import "sp-component";
156
+ import "sp-component/tokens.css";
103
157
 
104
158
  @NgModule({
105
159
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
@@ -109,11 +163,9 @@ export class AppModule {}
109
163
 
110
164
  ```html
111
165
  <!-- template -->
112
- <sp-input
113
- label="Username"
114
- [value]="username"
115
- (sp-input)="username = $event.detail.value"
116
- ></sp-input>
166
+ <sp-input label="Username" [value]="username" (sp-input)="username = $event.detail.value"></sp-input>
167
+
168
+ <sp-autocomplete label="Category" [options]="options" (sp-change)="onSelect($event.detail.value)"></sp-autocomplete>
117
169
 
118
170
  <sp-button variant="primary" (sp-click)="submit()">Submit</sp-button>
119
171
  ```
@@ -123,12 +175,13 @@ export class AppModule {}
123
175
  ### React
124
176
 
125
177
  ```tsx
126
- import "libreria-component";
178
+ import "sp-component";
179
+ import "sp-component/tokens.css";
127
180
 
128
181
  export function LoginForm() {
129
182
  const handleInput = (e: Event) => {
130
- const detail = (e as CustomEvent<{ value: string }>).detail;
131
- console.log(detail.value);
183
+ const { value } = (e as CustomEvent<{ value: string }>).detail;
184
+ console.log(value);
132
185
  };
133
186
 
134
187
  return (
@@ -140,7 +193,7 @@ export function LoginForm() {
140
193
  }
141
194
  ```
142
195
 
143
- > **Tip:** React 19+ supports custom element event props natively. For React 18 and earlier, attach events with `useRef` + `addEventListener`.
196
+ > **React 18 and earlier:** attach events via `useRef` + `addEventListener` since React 18 does not forward custom event props. React 19+ supports custom elements natively.
144
197
 
145
198
  ---
146
199
 
@@ -148,17 +201,19 @@ export function LoginForm() {
148
201
 
149
202
  ```vue
150
203
  <script setup>
151
- import "libreria-component";
204
+ import { ref } from "vue";
205
+ import "sp-component";
206
+ import "sp-component/tokens.css";
152
207
 
153
208
  const value = ref("");
209
+ const selected = ref([]);
154
210
  </script>
155
211
 
156
212
  <template>
157
- <sp-input
158
- label="Search"
159
- :value="value"
160
- @sp-input="value = $event.detail.value"
161
- />
213
+ <sp-input label="Search" :value="value" @sp-input="value = $event.detail.value" />
214
+
215
+ <sp-autocomplete label="Tags" :options="options" multiple @sp-change="selected = $event.detail.values" />
216
+
162
217
  <sp-button variant="primary" @sp-click="search">Search</sp-button>
163
218
  </template>
164
219
  ```
@@ -169,96 +224,98 @@ const value = ref("");
169
224
 
170
225
  ### Form Inputs
171
226
 
172
- | Component | Tag | Description |
173
- | ----------- | ------------------ | ----------------------------------------------- |
174
- | Input | `<sp-input>` | Text, email, password, number, search, tel, url |
175
- | Textarea | `<sp-textarea>` | Multi-line text input |
176
- | Checkbox | `<sp-checkbox>` | Single checkbox with label |
177
- | Radio | `<sp-radio>` | Radio button |
178
- | Switch | `<sp-switch>` | Toggle switch (on/off) |
179
- | Select | `<sp-select>` | Dropdown select |
180
- | Combobox | `<sp-combobox>` | Searchable select with keyboard navigation |
181
- | Slider | `<sp-slider>` | Range slider |
182
- | Rating | `<sp-rating>` | Star rating input |
183
- | OTP Input | `<sp-otp-input>` | One-time password digit input |
184
- | File Upload | `<sp-file-upload>` | File picker input |
185
- | Form Field | `<sp-form-field>` | Label + hint + error wrapper for any input |
227
+ | Component | Tag | Description |
228
+ | -------------- | --------------------- | -------------------------------------------------- |
229
+ | Input | `<sp-input>` | Text, email, password, number, search, tel, url |
230
+ | Textarea | `<sp-textarea>` | Multi-line text input |
231
+ | Checkbox | `<sp-checkbox>` | Single checkbox with label |
232
+ | Checkbox Group | `<sp-checkbox-group>` | Group of checkboxes |
233
+ | Radio | `<sp-radio>` | Radio button |
234
+ | Radio Group | `<sp-radio-group>` | Group of radio buttons |
235
+ | Switch | `<sp-switch>` | Toggle switch (on/off) |
236
+ | Select | `<sp-select>` | Dropdown select with optional multiple |
237
+ | Combobox | `<sp-combobox>` | Searchable select — single or multiple |
238
+ | Autocomplete | `<sp-autocomplete>` | Search with groups, descriptions, creatable, async |
239
+ | Number Input | `<sp-number-input>` | Numeric input with increment/decrement |
240
+ | Slider | `<sp-slider>` | Range slider |
241
+ | Rating | `<sp-rating>` | Star rating input |
242
+ | OTP Input | `<sp-otp-input>` | One-time password digit input |
243
+ | File Upload | `<sp-file-upload>` | Drag & drop file picker |
244
+ | Time Picker | `<sp-time-picker>` | Hour/minute/second picker |
245
+ | Color Picker | `<sp-color-picker>` | HSV color picker with hex input and swatches |
246
+ | Tag Input | `<sp-tag-input>` | Free-text tag creation input |
247
+ | Form Field | `<sp-form-field>` | Label + hint + error wrapper for any input |
186
248
 
187
249
  ### Buttons & Actions
188
250
 
189
- | Component | Tag | Description |
190
- | ----------- | ------------------ | -------------------------------------- |
191
- | Button | `<sp-button>` | Primary, secondary, ghost, destructive |
192
- | Copy Button | `<sp-copy-button>` | Copies text to clipboard |
251
+ | Component | Tag | Description |
252
+ | ----------- | ------------------ | -------------------------------------------- |
253
+ | Button | `<sp-button>` | Primary, secondary, ghost, destructive, link |
254
+ | Copy Button | `<sp-copy-button>` | Copies text to clipboard with feedback |
193
255
 
194
256
  ### Navigation
195
257
 
196
- | Component | Tag | Description |
197
- | ---------- | ------------------------------------------- | ----------------------------- |
198
- | Tabs | `<sp-tabs>` + `<sp-tab>` + `<sp-tab-panel>` | Tabbed navigation |
199
- | Breadcrumb | `<sp-breadcrumb>` + `<sp-breadcrumb-item>` | Page path navigation |
200
- | Pagination | `<sp-pagination>` | Page number navigation |
201
- | Navbar | `<sp-navbar>` | Top navigation bar |
202
- | Sidebar | `<sp-sidebar>` | Side navigation |
203
- | Stepper | `<sp-stepper>` | Multi-step progress indicator |
258
+ | Component | Tag | Description |
259
+ | ---------- | ------------------------------------------ | -------------------------------------- |
260
+ | Tabs | `<sp-tabs>` + `<sp-tab>` | Tabbed navigation |
261
+ | Breadcrumb | `<sp-breadcrumb>` + `<sp-breadcrumb-item>` | Page path navigation |
262
+ | Pagination | `<sp-pagination>` | Page number navigation with jump-to |
263
+ | Navbar | `<sp-navbar>` | Top navigation bar |
264
+ | Sidebar | `<sp-sidebar>` | Collapsible side navigation |
265
+ | Menu | `<sp-menu>` + `<sp-menu-item>` | Dropdown menu with keyboard navigation |
266
+ | Stepper | `<sp-stepper>` | Multi-step progress indicator |
204
267
 
205
268
  ### Overlays
206
269
 
207
- | Component | Tag | Description |
208
- | --------- | ------------------------------ | ------------------------------------------ |
209
- | Modal | `<sp-modal>` | Dialog with focus trap + ESC close |
210
- | Drawer | `<sp-drawer>` | Slide-in panel with focus trap + ESC close |
211
- | Popover | `<sp-popover>` | Anchored floating panel |
212
- | Tooltip | `<sp-tooltip>` | Hover/focus hint |
213
- | Toast | `<sp-toast>` | Temporary notification |
214
- | Menu | `<sp-menu>` + `<sp-menu-item>` | Dropdown menu with keyboard navigation |
215
-
216
- ### Display
217
-
218
- | Component | Tag | Description |
219
- | --------------- | ---------------------- | ---------------------------------------------- |
220
- | Card | `<sp-card>` | Content container |
221
- | Badge | `<sp-badge>` | Status indicator label |
222
- | Tag | `<sp-tag>` | Dismissible label |
223
- | Alert | `<sp-alert>` | Inline message (info, success, warning, error) |
224
- | Avatar | `<sp-avatar>` | User image or initials |
225
- | Icon | `<sp-icon>` | SVG icon wrapper |
226
- | Divider | `<sp-divider>` | Horizontal/vertical separator |
227
- | Stat | `<sp-stat>` | Metric display (value + label) |
228
- | Timeline | `<sp-timeline>` | Vertical event list |
229
- | Table | `<sp-table>` | Data table |
230
- | Empty State | `<sp-empty-state>` | Zero-data placeholder |
231
- | Accordion | `<sp-accordion-item>` | Collapsible content section |
232
- | Progress Bar | `<sp-progress-bar>` | Linear progress indicator |
233
- | Skeleton | `<sp-skeleton>` | Loading placeholder |
234
- | Spinner | `<sp-spinner>` | Loading spinner |
235
- | Visually Hidden | `<sp-visually-hidden>` | Screen reader only content |
236
-
237
- ---
238
-
239
- ## Customization
240
-
241
- All components expose CSS custom properties for theming. Example with `sp-button`:
242
-
243
- ```css
244
- sp-button {
245
- --sp-button-radius: 8px;
246
- --sp-button-font-size: 16px;
247
- --sp-button-transition: background 0.2s ease;
248
- }
249
- ```
250
-
251
- You can also target internal parts using `::part()`:
252
-
253
- ```css
254
- sp-input::part(input) {
255
- font-family: "Inter", sans-serif;
256
- }
257
-
258
- sp-button::part(button) {
259
- letter-spacing: 0.05em;
260
- }
261
- ```
270
+ | Component | Tag | Description |
271
+ | --------------- | ---------------------- | ------------------------------------------ |
272
+ | Modal | `<sp-modal>` | Dialog with focus trap + ESC close |
273
+ | Drawer | `<sp-drawer>` | Slide-in panel with focus trap + ESC close |
274
+ | Popover | `<sp-popover>` | Anchored floating panel |
275
+ | Tooltip | `<sp-tooltip>` | Hover/focus hint |
276
+ | Toast | `<sp-toast>` | Temporary notification |
277
+ | Toast Stack | `<sp-toast-stack>` | Container for stacked toasts |
278
+ | Confirm Dialog | `<sp-confirm-dialog>` | Confirmation prompt with accept/cancel |
279
+ | Command Palette | `<sp-command-palette>` | Spotlight-style command search |
280
+
281
+ ### Data Display
282
+
283
+ | Component | Tag | Description |
284
+ | -------------------- | ---------------------------------------- | ------------------------------------------ |
285
+ | Table | `<sp-table>` | Data table with sorting and selection |
286
+ | Card | `<sp-card>` | Content container with header/footer slots |
287
+ | Badge | `<sp-badge>` | Status indicator label |
288
+ | Tag | `<sp-tag>` | Dismissible label |
289
+ | Avatar | `<sp-avatar>` | User image or initials with status dot |
290
+ | Stat | `<sp-stat>` | Metric display (value + label + trend) |
291
+ | Timeline | `<sp-timeline>` | Vertical event list |
292
+ | Accordion | `<sp-accordion>` + `<sp-accordion-item>` | Collapsible content sections |
293
+ | Tree | `<sp-tree>` + `<sp-tree-item>` | Hierarchical data tree |
294
+ | Gallery | `<sp-gallery>` | Image grid with lightbox |
295
+ | Carousel | `<sp-carousel>` | Sliding content carousel |
296
+ | Calendar | `<sp-calendar>` | Month calendar with date selection |
297
+ | Calendar Date Picker | `<sp-calendar-date-picker>` | Input field with calendar popup |
298
+
299
+ ### Feedback & Status
300
+
301
+ | Component | Tag | Description |
302
+ | ------------ | ------------------- | ---------------------------------------------- |
303
+ | Alert | `<sp-alert>` | Inline message — info, success, warning, error |
304
+ | Progress Bar | `<sp-progress-bar>` | Linear progress indicator |
305
+ | Spinner | `<sp-spinner>` | Loading spinner |
306
+ | Skeleton | `<sp-skeleton>` | Loading placeholder |
307
+
308
+ ### Layout & Utilities
309
+
310
+ | Component | Tag | Description |
311
+ | --------------- | ---------------------- | ----------------------------------- |
312
+ | Divider | `<sp-divider>` | Horizontal/vertical separator |
313
+ | Split Panel | `<sp-split-panel>` | Resizable two-pane layout |
314
+ | Scroll Area | `<sp-scroll-area>` | Custom scrollbar container |
315
+ | Empty State | `<sp-empty-state>` | Zero-data placeholder with action |
316
+ | Icon | `<sp-icon>` | SVG icon wrapper with size variants |
317
+ | Kbd | `<sp-kbd>` | Keyboard key display |
318
+ | Visually Hidden | `<sp-visually-hidden>` | Screen-reader-only content |
262
319
 
263
320
  ---
264
321
 
@@ -266,20 +323,26 @@ sp-button::part(button) {
266
323
 
267
324
  All components emit prefixed custom events to avoid collisions with native DOM events.
268
325
 
269
- | Event | Detail | Description |
270
- | ----------- | ------------ | ---------------------------------------- |
271
- | `sp-click` | `{ source }` | Button clicked |
272
- | `sp-input` | `{ value }` | Input value changed (on every keystroke) |
273
- | `sp-change` | `{ value }` | Input value committed (on blur/enter) |
274
- | `sp-focus` | | Element received focus |
275
- | `sp-blur` | | Element lost focus |
276
- | `sp-clear` | — | Clear button clicked on input |
277
- | `sp-open` | — | Overlay opened (modal, drawer, popover) |
278
- | `sp-close` | — | Overlay closed |
326
+ | Event | Detail | Description |
327
+ | ----------- | --------------------------- | -------------------------------------------- |
328
+ | `sp-click` | `{ source }` | Button clicked |
329
+ | `sp-input` | `{ value }` | Input value changed (every keystroke) |
330
+ | `sp-change` | `{ value }` or `{ values }` | Selection committed |
331
+ | `sp-search` | `{ query }` | Autocomplete query changed (for async fetch) |
332
+ | `sp-create` | `{ label }` | User requested to create a new option |
333
+ | `sp-focus` | — | Element received focus |
334
+ | `sp-blur` | — | Element lost focus |
335
+ | `sp-clear` | — | Clear button clicked |
336
+ | `sp-open` | — | Overlay opened |
337
+ | `sp-close` | — | Overlay closed |
279
338
 
280
339
  ```js
281
340
  document.querySelector("sp-input").addEventListener("sp-input", (e) => {
282
- console.log(e.detail.value); // current value
341
+ console.log(e.detail.value);
342
+ });
343
+
344
+ document.querySelector("sp-autocomplete").addEventListener("sp-change", (e) => {
345
+ console.log(e.detail.values); // string[] in multiple mode
283
346
  });
284
347
  ```
285
348
 
@@ -287,21 +350,23 @@ document.querySelector("sp-input").addEventListener("sp-input", (e) => {
287
350
 
288
351
  ## Form Participation
289
352
 
290
- All form input components are **form-associated custom elements** — they work with native `<form>` just like `<input>` does.
353
+ All form input components are **form-associated custom elements** — they participate in native `<form>` submission and validation just like `<input>` does.
291
354
 
292
355
  ```html
293
- <form id="my-form">
356
+ <form id="signup-form">
294
357
  <sp-input name="email" type="email" required></sp-input>
295
358
  <sp-textarea name="message" required></sp-textarea>
296
- <sp-checkbox name="agree" value="yes"></sp-checkbox>
359
+ <sp-select name="role" required></sp-select>
360
+ <sp-checkbox name="agree" value="yes" required></sp-checkbox>
297
361
  <sp-button type="submit">Send</sp-button>
298
362
  </form>
299
363
 
300
364
  <script>
301
- document.getElementById("my-form").addEventListener("submit", (e) => {
365
+ document.getElementById("signup-form").addEventListener("submit", (e) => {
302
366
  e.preventDefault();
303
367
  const data = new FormData(e.target);
304
- console.log(Object.fromEntries(data)); // { email: "...", message: "...", agree: "yes" }
368
+ console.log(Object.fromEntries(data));
369
+ // { email: "...", message: "...", role: "...", agree: "yes" }
305
370
  });
306
371
  </script>
307
372
  ```
@@ -312,29 +377,29 @@ All form input components are **form-associated custom elements** — they work
312
377
 
313
378
  ```bash
314
379
  # Clone and install
315
- git clone https://github.com/wisftock/libreria-component.git
316
- cd libreria-component
380
+ git clone https://gitlab.com/wisftock/sp-component.git
381
+ cd sp-component
317
382
  npm install
318
383
 
319
- # Run Storybook (component explorer)
384
+ # Run Storybook
320
385
  npm run storybook
321
386
 
322
387
  # Run tests
323
388
  npm run test
324
389
 
325
- # Run tests in watch mode
326
- npm run test:watch
390
+ # Type check
391
+ npm run type-check
327
392
 
328
393
  # Build
329
394
  npm run build
330
395
  ```
331
396
 
332
- Before submitting a PR, ensure:
397
+ Before submitting a PR:
333
398
 
334
399
  ```bash
335
- npm run type-check # TypeScript — no errors
336
- npm run test # All 633 tests pass
337
- npm run build # Build succeeds
400
+ npm run type-check # 0 TypeScript errors
401
+ npm run test # 1010 tests passing
402
+ npm run build # dist/ generated correctly
338
403
  ```
339
404
 
340
405
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sp-component",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Librería de Web Components compatible con Angular, React, Vue y cualquier framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",