@liwe3/webcomponents 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 OS3 srl - Fabio Rotondo <fabio.rotondo@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,383 @@
1
+ # @liwe3/webcomponents
2
+
3
+ A collection of reusable, framework-agnostic web components built with TypeScript.
4
+
5
+ ## Features
6
+
7
+ - **SmartSelect**: A customizable select dropdown with search, multi-select, and keyboard navigation
8
+ - **AITextEditor**: A text editor with AI-powered text continuation suggestions
9
+ - Framework-agnostic (works with vanilla JS, React, Vue, Svelte, Angular, etc.)
10
+ - TypeScript support with full type definitions
11
+ - Zero dependencies (web components only)
12
+ - Tree-shakeable - import only what you need
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @liwe3/webcomponents
18
+ # or
19
+ pnpm add @liwe3/webcomponents
20
+ # or
21
+ yarn add @liwe3/webcomponents
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### Import All Components
27
+
28
+ ```typescript
29
+ import '@liwe3/webcomponents';
30
+ ```
31
+
32
+ ### Import Individual Components
33
+
34
+ ```typescript
35
+ // Import only SmartSelect
36
+ import '@liwe3/webcomponents/smart-select';
37
+
38
+ // Import only AITextEditor
39
+ import '@liwe3/webcomponents/ai-text-editor';
40
+ ```
41
+
42
+ ### Using with TypeScript
43
+
44
+ ```typescript
45
+ import { SmartSelectElement, AITextEditorElement, type SelectOption } from '@liwe3/webcomponents';
46
+
47
+ // Access element instances with proper typing
48
+ const select = document.querySelector('liwe3-select') as SmartSelectElement;
49
+ select.setOptions([
50
+ { value: '1', label: 'Option 1' },
51
+ { value: '2', label: 'Option 2' }
52
+ ]);
53
+ ```
54
+
55
+ ## Components
56
+
57
+ ### SmartSelect
58
+
59
+ A powerful select dropdown with advanced features.
60
+
61
+ #### Features
62
+
63
+ - Single and multi-select modes
64
+ - Search/filter options
65
+ - Keyboard navigation (Arrow keys, Enter, Escape, Tab)
66
+ - Custom styling via CSS variables
67
+ - Automatic positioning (viewport-aware)
68
+ - Full TypeScript support
69
+
70
+ #### Basic Usage
71
+
72
+ ```html
73
+ <liwe3-select
74
+ placeholder="Select an option"
75
+ searchable
76
+ multiple
77
+ ></liwe3-select>
78
+
79
+ <script type="module">
80
+ import '@liwe3/webcomponents/smart-select';
81
+
82
+ const select = document.querySelector('liwe3-select');
83
+
84
+ // Set options
85
+ select.options = [
86
+ { value: 'js', label: 'JavaScript' },
87
+ { value: 'ts', label: 'TypeScript' },
88
+ { value: 'py', label: 'Python' }
89
+ ];
90
+
91
+ // Listen for changes
92
+ select.addEventListener('change', (e) => {
93
+ console.log('Selected:', e.detail.value);
94
+ });
95
+ </script>
96
+ ```
97
+
98
+ #### Attributes
99
+
100
+ - `multiple` - Enable multi-select mode
101
+ - `searchable` - Enable search/filter functionality
102
+ - `placeholder` - Placeholder text (default: "Select an option")
103
+ - `disabled` - Disable the select
104
+
105
+ #### Properties
106
+
107
+ ```typescript
108
+ // Get/set value
109
+ select.value; // string | string[]
110
+ select.value = 'js'; // Set single value
111
+ select.value = ['js', 'ts']; // Set multiple values (when multiple=true)
112
+
113
+ // Get/set options
114
+ select.options; // SelectOption[]
115
+ select.setOptions([...]);
116
+
117
+ // Control dropdown
118
+ select.open();
119
+ select.close();
120
+ select.toggle();
121
+
122
+ // Select/deselect options
123
+ select.selectOption('js');
124
+ select.deselectOption('js');
125
+ select.getSelectedOptions(); // SelectOption[]
126
+ ```
127
+
128
+ #### Events
129
+
130
+ - `change` - Fired when selection changes (detail: { value })
131
+ - `open` - Fired when dropdown opens
132
+ - `close` - Fired when dropdown closes
133
+ - `search` - Fired when search query changes (detail: { query })
134
+
135
+ #### CSS Variables
136
+
137
+ ```css
138
+ liwe3-select {
139
+ --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
140
+ --font-size: 14px;
141
+ --padding: 8px 12px;
142
+ --border: 1px solid #ccc;
143
+ --border-radius: 4px;
144
+ --background: white;
145
+ --focus-color: #007bff;
146
+
147
+ /* Tag styles (multi-select) */
148
+ --tag-background: #e9ecef;
149
+ --tag-border-radius: 12px;
150
+ --tag-color: #495057;
151
+ --remove-color: #6c757d;
152
+ --remove-hover-color: #dc3545;
153
+
154
+ /* Dropdown styles */
155
+ --dropdown-background: white;
156
+ --dropdown-border: 1px solid #ccc;
157
+ --dropdown-border-radius: 4px;
158
+ --dropdown-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
159
+
160
+ /* Option styles */
161
+ --option-color: #333;
162
+ --option-hover-background: #f8f9fa;
163
+ --option-focused-background: #007bff;
164
+ --option-focused-color: white;
165
+ --option-selected-background: #e3f2fd;
166
+ --option-selected-color: #1976d2;
167
+ --no-options-color: #6c757d;
168
+ }
169
+ ```
170
+
171
+ ### AITextEditor
172
+
173
+ A text editor with AI-powered suggestions.
174
+
175
+ #### Features
176
+
177
+ - AI-powered text continuation
178
+ - Configurable AI endpoint (OpenAI, LM Studio, etc.)
179
+ - Tab to accept suggestions
180
+ - Escape to dismiss
181
+ - Paragraph-by-paragraph acceptance
182
+ - localStorage API key management
183
+ - Custom system prompts
184
+ - Context support for better suggestions
185
+
186
+ #### Basic Usage
187
+
188
+ ```html
189
+ <liwe3-ai-text-editor style="width: 100%; height: 400px;"></liwe3-ai-text-editor>
190
+
191
+ <script type="module">
192
+ import '@liwe3/webcomponents/ai-text-editor';
193
+
194
+ const editor = document.querySelector('liwe3-ai-text-editor');
195
+
196
+ // Configure API
197
+ editor.setApiKey('your-api-key');
198
+ editor.setApiEndpoint('https://api.openai.com/v1/chat/completions');
199
+ editor.setModelName('gpt-3.5-turbo');
200
+
201
+ // Set initial text
202
+ editor.setText('Once upon a time...');
203
+
204
+ // Listen for changes
205
+ editor.addEventListener('change', (e) => {
206
+ console.log('Text:', e.detail.value);
207
+ });
208
+
209
+ // Handle before suggestion (optional - can cancel)
210
+ editor.addEventListener('beforeSuggestion', (e) => {
211
+ // Cancel suggestion if needed
212
+ if (someCondition) {
213
+ e.preventDefault();
214
+ }
215
+ });
216
+ </script>
217
+ ```
218
+
219
+ #### Properties & Methods
220
+
221
+ ```typescript
222
+ // Text content
223
+ editor.setText(text: string): void;
224
+ editor.getText(): string;
225
+
226
+ // API configuration
227
+ editor.setApiKey(key: string): void;
228
+ editor.getApiKey(): string;
229
+ editor.setApiEndpoint(endpoint: string): void;
230
+ editor.getApiEndpoint(): string;
231
+ editor.setModelName(modelName: string): void;
232
+ editor.getModelName(): string;
233
+
234
+ // Suggestion settings
235
+ editor.setSuggestionDelay(seconds: number): void; // Default: 1 second
236
+ editor.getSuggestionDelay(): number;
237
+ editor.setSystemPrompt(prompt: string): void;
238
+ editor.getSystemPrompt(): string;
239
+
240
+ // Context for better suggestions
241
+ editor.setContext(context: string): void;
242
+ editor.getContext(): string;
243
+ ```
244
+
245
+ #### Events
246
+
247
+ - `change` - Fired when text changes (detail: { value })
248
+ - `beforeSuggestion` - Fired before requesting AI suggestion (cancelable)
249
+ - detail: { text, context, apiEndpoint, modelName, systemPrompt }
250
+ - `error` - Fired when an error occurs (detail: { message })
251
+
252
+ #### Keyboard Shortcuts
253
+
254
+ - `Tab` - Accept current suggestion paragraph
255
+ - `Escape` - Dismiss suggestion
256
+ - Arrow keys/Click - Dismiss suggestion and move cursor
257
+
258
+ #### Using with Local LM Studio
259
+
260
+ ```javascript
261
+ editor.setApiEndpoint('http://localhost:1234/v1/chat/completions');
262
+ editor.setModelName('local-model');
263
+ editor.setApiKey(''); // No API key needed for local
264
+ ```
265
+
266
+ ## Custom Tag Names
267
+
268
+ You can register components with custom tag names:
269
+
270
+ ```typescript
271
+ import { defineSmartSelect, defineAITextEditor } from '@liwe3/webcomponents';
272
+
273
+ defineSmartSelect('my-select');
274
+ defineAITextEditor('my-editor');
275
+ ```
276
+
277
+ ```html
278
+ <my-select></my-select>
279
+ <my-editor></my-editor>
280
+ ```
281
+
282
+ ## Framework Integration
283
+
284
+ ### React
285
+
286
+ ```tsx
287
+ import '@liwe3/webcomponents';
288
+ import { useRef, useEffect } from 'react';
289
+ import type { SmartSelectElement } from '@liwe3/webcomponents';
290
+
291
+ function MyComponent() {
292
+ const selectRef = useRef<SmartSelectElement>(null);
293
+
294
+ useEffect(() => {
295
+ if (selectRef.current) {
296
+ selectRef.current.setOptions([
297
+ { value: '1', label: 'Option 1' },
298
+ { value: '2', label: 'Option 2' }
299
+ ]);
300
+ }
301
+ }, []);
302
+
303
+ return <liwe3-select ref={selectRef} />;
304
+ }
305
+ ```
306
+
307
+ ### Vue
308
+
309
+ ```vue
310
+ <template>
311
+ <liwe3-select ref="select" @change="handleChange" />
312
+ </template>
313
+
314
+ <script setup>
315
+ import '@liwe3/webcomponents';
316
+ import { ref, onMounted } from 'vue';
317
+
318
+ const select = ref(null);
319
+
320
+ onMounted(() => {
321
+ select.value.setOptions([
322
+ { value: '1', label: 'Option 1' },
323
+ { value: '2', label: 'Option 2' }
324
+ ]);
325
+ });
326
+
327
+ const handleChange = (e) => {
328
+ console.log('Selected:', e.detail.value);
329
+ };
330
+ </script>
331
+ ```
332
+
333
+ ### Svelte
334
+
335
+ ```svelte
336
+ <script>
337
+ import '@liwe3/webcomponents';
338
+ import { onMount } from 'svelte';
339
+
340
+ let selectElement;
341
+
342
+ onMount(() => {
343
+ selectElement.setOptions([
344
+ { value: '1', label: 'Option 1' },
345
+ { value: '2', label: 'Option 2' }
346
+ ]);
347
+ });
348
+
349
+ const handleChange = (e) => {
350
+ console.log('Selected:', e.detail.value);
351
+ };
352
+ </script>
353
+
354
+ <liwe3-select bind:this={selectElement} on:change={handleChange} />
355
+ ```
356
+
357
+ ## Browser Support
358
+
359
+ Modern browsers with Web Components support:
360
+ - Chrome/Edge 67+
361
+ - Firefox 63+
362
+ - Safari 10.1+
363
+
364
+ ## Development
365
+
366
+ ```bash
367
+ # Install dependencies
368
+ pnpm install
369
+
370
+ # Build
371
+ pnpm run build
372
+
373
+ # Build in watch mode
374
+ pnpm run dev
375
+ ```
376
+
377
+ ## License
378
+
379
+ MIT
380
+
381
+ ## Contributing
382
+
383
+ Contributions are welcome! Please feel free to submit a Pull Request.