@colletdev/core 0.1.3 → 0.1.5
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/custom-elements.json +16 -0
- package/generated/index.js +1 -1
- package/package.json +12 -2
- package/src/elements/chat_input.js +45 -1
- package/src/elements/pagination.d.ts +2 -0
- package/src/elements/pagination.js +1 -1
- package/src/purge.mjs +67 -0
- package/src/runtime.js +6 -0
- package/src/server.js +7 -3
- package/wasm/wasm_api_bg.wasm +0 -0
package/custom-elements.json
CHANGED
|
@@ -2903,6 +2903,14 @@
|
|
|
2903
2903
|
"default": "false",
|
|
2904
2904
|
"fieldName": "show_prev_next"
|
|
2905
2905
|
},
|
|
2906
|
+
{
|
|
2907
|
+
"name": "variant",
|
|
2908
|
+
"type": {
|
|
2909
|
+
"text": "string"
|
|
2910
|
+
},
|
|
2911
|
+
"default": "\"\"",
|
|
2912
|
+
"fieldName": "variant"
|
|
2913
|
+
},
|
|
2906
2914
|
{
|
|
2907
2915
|
"name": "prev-label",
|
|
2908
2916
|
"type": {
|
|
@@ -2919,6 +2927,14 @@
|
|
|
2919
2927
|
"default": "\"\"",
|
|
2920
2928
|
"fieldName": "next_label"
|
|
2921
2929
|
},
|
|
2930
|
+
{
|
|
2931
|
+
"name": "load-more-label",
|
|
2932
|
+
"type": {
|
|
2933
|
+
"text": "string"
|
|
2934
|
+
},
|
|
2935
|
+
"default": "\"\"",
|
|
2936
|
+
"fieldName": "load_more_label"
|
|
2937
|
+
},
|
|
2922
2938
|
{
|
|
2923
2939
|
"name": "page-size-options",
|
|
2924
2940
|
"type": {
|
package/generated/index.js
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
import { initWasm, loadSharedStyles, loadInlineSharedStyles, loadMotionStyles, loadInlineMotionStyles, injectTokensToHead, injectFoucPrevention, CxElement, CxFormElement } from '../src/runtime.js';
|
|
24
24
|
|
|
25
25
|
// Package version — used for CDN fallback URL
|
|
26
|
-
const PKG_VERSION = '0.1.
|
|
26
|
+
const PKG_VERSION = '0.1.4';
|
|
27
27
|
|
|
28
28
|
// ─── Lazy WASM + CSS ───
|
|
29
29
|
// WASM glue and CSS strings are NOT imported at module level.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colletdev/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Rust/WASM Custom Elements — 48 production-grade UI components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "generated/index.js",
|
|
@@ -40,8 +40,18 @@
|
|
|
40
40
|
"wasm/",
|
|
41
41
|
"custom-elements.json"
|
|
42
42
|
],
|
|
43
|
+
"bin": {
|
|
44
|
+
"collet-purge": "src/purge.mjs"
|
|
45
|
+
},
|
|
43
46
|
"customElements": "custom-elements.json",
|
|
44
|
-
"keywords": [
|
|
47
|
+
"keywords": [
|
|
48
|
+
"web-components",
|
|
49
|
+
"custom-elements",
|
|
50
|
+
"rust",
|
|
51
|
+
"wasm",
|
|
52
|
+
"ui",
|
|
53
|
+
"design-system"
|
|
54
|
+
],
|
|
45
55
|
"author": "Dan",
|
|
46
56
|
"license": "MIT",
|
|
47
57
|
"sideEffects": false,
|
|
@@ -20,10 +20,11 @@ export function defineCxChatInput(wasmFn, baseClass) {
|
|
|
20
20
|
if (!this._isInitialized) {
|
|
21
21
|
this._markInitialized();
|
|
22
22
|
|
|
23
|
-
// Input event delegation for cx-input
|
|
23
|
+
// Input event delegation for cx-input + multiline detection
|
|
24
24
|
this._shadow.addEventListener('input', (e) => {
|
|
25
25
|
if (e.target.tagName === 'TEXTAREA') {
|
|
26
26
|
this._emit('cx-input', { value: e.target.value });
|
|
27
|
+
this.#detectMultiline(e.target);
|
|
27
28
|
}
|
|
28
29
|
});
|
|
29
30
|
|
|
@@ -56,6 +57,33 @@ export function defineCxChatInput(wasmFn, baseClass) {
|
|
|
56
57
|
super.connectedCallback();
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
// ── Multiline Detection ──
|
|
61
|
+
// Toggles `data-multiline` on the container when textarea exceeds one row.
|
|
62
|
+
// CSS drives the pill→rounded morph via `data-[multiline]:rounded-2xl` and
|
|
63
|
+
// `group-data-[multiline]:` selectors on child elements.
|
|
64
|
+
#detectMultiline(textarea) {
|
|
65
|
+
const container = textarea.closest('[data-chat-input]');
|
|
66
|
+
if (!container) return;
|
|
67
|
+
|
|
68
|
+
// Store baseline height on first measure (single-line height).
|
|
69
|
+
if (!textarea._baseH) {
|
|
70
|
+
textarea._baseH = textarea.scrollHeight;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const hasNewline = textarea.value.includes('\n');
|
|
74
|
+
const hasOverflow = textarea._baseH ? textarea.scrollHeight > textarea._baseH + 2 : false;
|
|
75
|
+
const isMulti = hasNewline || hasOverflow;
|
|
76
|
+
const current = container.hasAttribute('data-multiline');
|
|
77
|
+
|
|
78
|
+
if (isMulti !== current) {
|
|
79
|
+
if (isMulti) {
|
|
80
|
+
container.setAttribute('data-multiline', '');
|
|
81
|
+
} else {
|
|
82
|
+
container.removeAttribute('data-multiline');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
59
87
|
// ── Public imperative API ──
|
|
60
88
|
focus() {
|
|
61
89
|
const el = this._shadow.querySelector('textarea');
|
|
@@ -64,9 +92,25 @@ export function defineCxChatInput(wasmFn, baseClass) {
|
|
|
64
92
|
|
|
65
93
|
_doRender() {
|
|
66
94
|
try {
|
|
95
|
+
// Preserve textarea value across re-renders (innerHTML replacement).
|
|
96
|
+
const prevTextarea = this._shadow.querySelector('textarea');
|
|
97
|
+
const savedValue = prevTextarea?.value || '';
|
|
98
|
+
|
|
67
99
|
this._props.slotted = true;
|
|
68
100
|
const result = wasmFn(this._props);
|
|
69
101
|
this._injectHtml(result);
|
|
102
|
+
|
|
103
|
+
// Restore textarea value and re-measure multiline state.
|
|
104
|
+
const textarea = this._shadow.querySelector('textarea');
|
|
105
|
+
if (textarea && savedValue) {
|
|
106
|
+
textarea.value = savedValue;
|
|
107
|
+
requestAnimationFrame(() => this.#detectMultiline(textarea));
|
|
108
|
+
} else if (textarea) {
|
|
109
|
+
// First render: measure baseline height.
|
|
110
|
+
requestAnimationFrame(() => {
|
|
111
|
+
textarea._baseH = textarea.scrollHeight;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
70
114
|
} catch (e) {
|
|
71
115
|
console.error('[cx-chat-input]', e);
|
|
72
116
|
}
|
|
@@ -10,8 +10,10 @@ export interface CxPaginationAttributes {
|
|
|
10
10
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
11
11
|
showInfo?: boolean;
|
|
12
12
|
showPrevNext?: boolean;
|
|
13
|
+
variant?: string;
|
|
13
14
|
prevLabel?: string;
|
|
14
15
|
nextLabel?: string;
|
|
16
|
+
loadMoreLabel?: string;
|
|
15
17
|
pageSizeOptions?: string;
|
|
16
18
|
}
|
|
17
19
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
export function defineCxPagination(wasmFn, baseClass) {
|
|
5
5
|
class CxPagination extends baseClass {
|
|
6
|
-
static observedAttributes = ['id', 'current-page', 'page-size', 'total-items', 'label', 'size', 'show-info', 'show-prev-next', 'prev-label', 'next-label', 'page-size-options'];
|
|
6
|
+
static observedAttributes = ['id', 'current-page', 'page-size', 'total-items', 'label', 'size', 'show-info', 'show-prev-next', 'variant', 'prev-label', 'next-label', 'load-more-label', 'page-size-options'];
|
|
7
7
|
static _booleanAttrs = new Set(['show-info', 'show-prev-next']);
|
|
8
8
|
static _numericAttrs = new Set(['current-page', 'page-size', 'total-items']);
|
|
9
9
|
static _hostDisplay = 'block';
|
package/src/purge.mjs
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// collet-purge — Clear stale WASM, CSS, and Vite cache artifacts after upgrading.
|
|
3
|
+
//
|
|
4
|
+
// Usage:
|
|
5
|
+
// npx @colletdev/core purge # clear caches and stale artifacts
|
|
6
|
+
// npx collet-purge # same thing
|
|
7
|
+
//
|
|
8
|
+
// What it clears:
|
|
9
|
+
// 1. Vite dep cache (.vite/) — forces re-optimization with new WASM
|
|
10
|
+
// 2. Vite build cache (node_modules/.vite/) — stale pre-bundled modules
|
|
11
|
+
// 3. Copied WASM in public/ — replaced by fresh binary from package
|
|
12
|
+
// 4. Old @collet/ scope packages — if migrating from @collet to @colletdev
|
|
13
|
+
//
|
|
14
|
+
// This is safe to run at any time — Vite rebuilds its cache on next dev start.
|
|
15
|
+
|
|
16
|
+
import { existsSync, rmSync, readdirSync } from 'node:fs';
|
|
17
|
+
import { resolve, join } from 'node:path';
|
|
18
|
+
|
|
19
|
+
const CWD = process.cwd();
|
|
20
|
+
let cleared = 0;
|
|
21
|
+
|
|
22
|
+
function rm(path, label) {
|
|
23
|
+
if (existsSync(path)) {
|
|
24
|
+
rmSync(path, { recursive: true, force: true });
|
|
25
|
+
console.log(` Cleared: ${label}`);
|
|
26
|
+
cleared++;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.log('');
|
|
31
|
+
console.log('Collet Purge — clearing stale artifacts');
|
|
32
|
+
console.log('─'.repeat(45));
|
|
33
|
+
|
|
34
|
+
// 1. Vite dep optimization cache
|
|
35
|
+
rm(resolve(CWD, 'node_modules/.vite'), 'node_modules/.vite/ (Vite dep cache)');
|
|
36
|
+
|
|
37
|
+
// 2. Vite build cache in project root
|
|
38
|
+
rm(resolve(CWD, '.vite'), '.vite/ (Vite build cache)');
|
|
39
|
+
|
|
40
|
+
// 3. Stale WASM binary copied to public/
|
|
41
|
+
rm(resolve(CWD, 'public/wasm_api_bg.wasm'), 'public/wasm_api_bg.wasm (stale WASM copy)');
|
|
42
|
+
|
|
43
|
+
// 4. Old @collet/ scope packages (pre-rename)
|
|
44
|
+
const oldScopeDir = resolve(CWD, 'node_modules/@collet');
|
|
45
|
+
if (existsSync(oldScopeDir)) {
|
|
46
|
+
try {
|
|
47
|
+
const entries = readdirSync(oldScopeDir);
|
|
48
|
+
if (entries.length > 0) {
|
|
49
|
+
rm(oldScopeDir, '@collet/ (old scope — migrate to @colletdev/)');
|
|
50
|
+
}
|
|
51
|
+
} catch { /* permission error — skip */ }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 5. Framework-specific caches
|
|
55
|
+
rm(resolve(CWD, '.next/cache'), '.next/cache/ (Next.js build cache)');
|
|
56
|
+
rm(resolve(CWD, '.nuxt'), '.nuxt/ (Nuxt build cache)');
|
|
57
|
+
rm(resolve(CWD, '.svelte-kit'), '.svelte-kit/ (SvelteKit build cache)');
|
|
58
|
+
rm(resolve(CWD, '.angular/cache'), '.angular/cache/ (Angular build cache)');
|
|
59
|
+
|
|
60
|
+
console.log('');
|
|
61
|
+
if (cleared === 0) {
|
|
62
|
+
console.log('Nothing to clear — caches are clean.');
|
|
63
|
+
} else {
|
|
64
|
+
console.log(`Cleared ${cleared} stale artifact${cleared > 1 ? 's' : ''}.`);
|
|
65
|
+
console.log('Run your dev server to rebuild fresh caches.');
|
|
66
|
+
}
|
|
67
|
+
console.log('');
|
package/src/runtime.js
CHANGED
|
@@ -231,6 +231,12 @@ const compatSheet = createSyncSheet([
|
|
|
231
231
|
// Scoped to [data-check] so it doesn't break "hidden data-[open]:block" on dropdowns.
|
|
232
232
|
'[data-check].hidden { display: none !important; }',
|
|
233
233
|
'',
|
|
234
|
+
// Tailwind v4 press/scale compat: MicroInteraction::press() generates
|
|
235
|
+
// `transition-transform active:scale-[0.97]`. TW4 uses the individual CSS
|
|
236
|
+
// `scale` property (not `transform: scale(...)`). `transition: transform`
|
|
237
|
+
// won't animate it. This rule overrides the transition to target `scale`.
|
|
238
|
+
'.transition-transform { transition-property: scale !important; }',
|
|
239
|
+
'',
|
|
234
240
|
// Ensure border-box in shadow DOM (Tailwind preflight may not load first)
|
|
235
241
|
'*, *::before, *::after { box-sizing: border-box; }',
|
|
236
242
|
'',
|
package/src/server.js
CHANGED
|
@@ -114,7 +114,11 @@ export async function createRenderer(options = {}) {
|
|
|
114
114
|
* @returns {{ html: string, sprites: string, a11y: object }}
|
|
115
115
|
*/
|
|
116
116
|
function renderToString(component, config) {
|
|
117
|
-
|
|
117
|
+
// Always enable slot mode so shadow HTML includes <slot> elements.
|
|
118
|
+
// Without this, slot-based components (text, card, dialog, drawer, etc.)
|
|
119
|
+
// render empty containers because content comes from light DOM children,
|
|
120
|
+
// not the config object.
|
|
121
|
+
const result = cx_render(component, { ...config, slotted: true });
|
|
118
122
|
return result;
|
|
119
123
|
}
|
|
120
124
|
|
|
@@ -135,7 +139,7 @@ export async function createRenderer(options = {}) {
|
|
|
135
139
|
* @returns {string} Full HTML string ready for insertion into a document
|
|
136
140
|
*/
|
|
137
141
|
function renderDSD(component, config, children = '') {
|
|
138
|
-
const result = cx_render(component, config);
|
|
142
|
+
const result = cx_render(component, { ...config, slotted: true });
|
|
139
143
|
const tag = `cx-${component.replace(/_/g, '-')}`;
|
|
140
144
|
const attrs = propsToAttributes(config);
|
|
141
145
|
const styles = stylesheetBlock();
|
|
@@ -156,7 +160,7 @@ export async function createRenderer(options = {}) {
|
|
|
156
160
|
* @returns {string} `<template shadowrootmode="open">...</template>`
|
|
157
161
|
*/
|
|
158
162
|
function renderDSDFragment(component, config) {
|
|
159
|
-
const result = cx_render(component, config);
|
|
163
|
+
const result = cx_render(component, { ...config, slotted: true });
|
|
160
164
|
const styles = stylesheetBlock();
|
|
161
165
|
const shadow = `${styles}${result.sprites}${result.html}`;
|
|
162
166
|
return `<template shadowrootmode="open">${shadow}</template>`;
|
package/wasm/wasm_api_bg.wasm
CHANGED
|
Binary file
|