anentrypoint-design 0.0.29 → 0.0.31

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anentrypoint-design",
3
- "version": "0.0.29",
3
+ "version": "0.0.31",
4
4
  "description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
5
5
  "type": "module",
6
6
  "main": "./dist/247420.js",
@@ -0,0 +1,105 @@
1
+ import * as webjsx from '../../vendor/webjsx/index.js';
2
+ import { Btn } from './shell.js';
3
+ import { fileGlyph, fmtFileSize } from './files.js';
4
+ const h = webjsx.createElement;
5
+
6
+ function Backdrop({ onClose, children, kind = '' } = {}) {
7
+ return h('div', {
8
+ class: 'ds-modal-backdrop',
9
+ onclick: (e) => { if (e.target === e.currentTarget && onClose) onClose(); }
10
+ },
11
+ h('div', { class: 'ds-modal' + (kind ? ' ds-modal-' + kind : '') }, ...(Array.isArray(children) ? children : [children]))
12
+ );
13
+ }
14
+
15
+ export function ConfirmDialog({ title = 'confirm', message, confirmLabel = 'confirm', cancelLabel = 'cancel', destructive, onConfirm, onCancel } = {}) {
16
+ return Backdrop({
17
+ onClose: onCancel,
18
+ kind: 'small',
19
+ children: [
20
+ h('div', { class: 'ds-modal-head' }, title),
21
+ h('div', { class: 'ds-modal-body' }, message || ''),
22
+ h('div', { class: 'ds-modal-actions' },
23
+ Btn({ onClick: onCancel, children: cancelLabel }),
24
+ h('button', {
25
+ class: destructive ? 'btn-stamp flame' : 'btn-stamp green',
26
+ onclick: onConfirm
27
+ }, confirmLabel)
28
+ )
29
+ ]
30
+ });
31
+ }
32
+
33
+ export function PromptDialog({ title = 'name', value = '', placeholder = '', confirmLabel = 'ok', cancelLabel = 'cancel', onConfirm, onCancel, onInput } = {}) {
34
+ return Backdrop({
35
+ onClose: onCancel,
36
+ kind: 'small',
37
+ children: [
38
+ h('div', { class: 'ds-modal-head' }, title),
39
+ h('div', { class: 'ds-modal-body' },
40
+ h('input', {
41
+ class: 'input ds-modal-input',
42
+ type: 'text',
43
+ value,
44
+ placeholder,
45
+ autofocus: true,
46
+ oninput: (e) => onInput && onInput(e.target.value),
47
+ onkeydown: (e) => {
48
+ if (e.key === 'Enter') { e.preventDefault(); onConfirm && onConfirm(e.target.value); }
49
+ if (e.key === 'Escape') { e.preventDefault(); onCancel && onCancel(); }
50
+ }
51
+ })
52
+ ),
53
+ h('div', { class: 'ds-modal-actions' },
54
+ Btn({ onClick: onCancel, children: cancelLabel }),
55
+ h('button', { class: 'btn-stamp green', onclick: () => onConfirm && onConfirm(value) }, confirmLabel)
56
+ )
57
+ ]
58
+ });
59
+ }
60
+
61
+ export function FilePreviewMedia({ src, type = 'other', name } = {}) {
62
+ if (type === 'image') return h('img', { class: 'ds-preview-media', src, alt: name || '' });
63
+ if (type === 'video') return h('video', { class: 'ds-preview-media', src, controls: true });
64
+ if (type === 'audio') return h('audio', { class: 'ds-preview-audio', src, controls: true });
65
+ return h('div', { class: 'ds-preview-fallback' },
66
+ h('span', { class: 'ds-preview-glyph' }, fileGlyph(type)),
67
+ h('span', {}, 'no inline preview for ' + (type || 'this file'))
68
+ );
69
+ }
70
+
71
+ export function FilePreviewCode({ content = '', lang } = {}) {
72
+ return h('pre', { class: 'ds-preview-code' + (lang ? ' lang-' + lang : '') },
73
+ h('code', { class: lang ? 'language-' + lang : '' }, content)
74
+ );
75
+ }
76
+
77
+ export function FilePreviewText({ content = '', truncated } = {}) {
78
+ return h('pre', { class: 'ds-preview-text' },
79
+ h('code', {}, content),
80
+ truncated ? h('div', { class: 'ds-preview-truncated' }, '… (truncated)') : null
81
+ );
82
+ }
83
+
84
+ export function FileViewer({ file, body, onClose, onAction } = {}) {
85
+ if (!file) return null;
86
+ const meta = [file.type, file.size != null ? fmtFileSize(file.size) : null, file.modified || null]
87
+ .filter(Boolean).join(' · ');
88
+ return Backdrop({
89
+ onClose,
90
+ kind: 'preview',
91
+ children: [
92
+ h('div', { class: 'ds-modal-head ds-preview-head', 'data-file-type': file.type || 'other' },
93
+ h('span', { class: 'ds-preview-name' }, file.name || ''),
94
+ h('span', { class: 'ds-preview-meta' }, meta),
95
+ h('span', { class: 'ds-preview-actions' },
96
+ onAction ? h('button', { class: 'ds-file-act', title: 'download', onclick: () => onAction('download') }, '↓') : null,
97
+ h('button', { class: 'ds-file-act', title: 'close', onclick: onClose }, '✕')
98
+ )
99
+ ),
100
+ h('div', { class: 'ds-preview-body', 'data-file-type': file.type || 'other' },
101
+ ...(Array.isArray(body) ? body : [body])
102
+ )
103
+ ]
104
+ });
105
+ }
@@ -0,0 +1,126 @@
1
+ import * as webjsx from '../../vendor/webjsx/index.js';
2
+ import { Btn, Glyph } from './shell.js';
3
+ const h = webjsx.createElement;
4
+
5
+ const FILE_TYPES = ['dir', 'image', 'video', 'audio', 'code', 'text', 'archive', 'document', 'symlink', 'other'];
6
+ const TYPE_GLYPH = {
7
+ dir: '▣', image: '◰', video: '▰', audio: '◎', code: '⌘',
8
+ text: '§', archive: '◐', document: '▢', symlink: '↗', other: '◌'
9
+ };
10
+
11
+ export function fileGlyph(type) {
12
+ return TYPE_GLYPH[type] || TYPE_GLYPH.other;
13
+ }
14
+
15
+ export function fmtFileSize(bytes) {
16
+ if (bytes == null || bytes === 0) return '—';
17
+ const u = ['B', 'KB', 'MB', 'GB', 'TB'];
18
+ let i = 0, n = bytes;
19
+ while (n >= 1024 && i < u.length - 1) { n /= 1024; i++; }
20
+ return n.toFixed(i === 0 ? 0 : 1) + ' ' + u[i];
21
+ }
22
+
23
+ export function FileIcon({ type = 'other' } = {}) {
24
+ return h('span', { class: 'ds-file-icon', 'data-file-type': type }, fileGlyph(type));
25
+ }
26
+
27
+ export function FileRow({ name, type = 'other', size, modified, code, onOpen, onAction, active, key } = {}) {
28
+ const meta = [type === 'dir' ? null : fmtFileSize(size), modified || null].filter(Boolean).join(' · ');
29
+ return h('div', {
30
+ key,
31
+ class: 'ds-file-row row' + (active ? ' active' : ''),
32
+ 'data-file-type': type,
33
+ onclick: onOpen
34
+ },
35
+ code != null ? h('span', { class: 'code' }, code) : null,
36
+ FileIcon({ type }),
37
+ h('span', { class: 'title' }, name),
38
+ h('span', { class: 'ds-file-meta meta' }, meta || '—'),
39
+ onAction ? h('span', { class: 'ds-file-actions', onclick: (e) => e.stopPropagation() },
40
+ h('button', { class: 'ds-file-act', title: 'download', onclick: () => onAction('download') }, '↓'),
41
+ h('button', { class: 'ds-file-act', title: 'rename', onclick: () => onAction('rename') }, '✎'),
42
+ h('button', { class: 'ds-file-act ds-file-act-warn', title: 'delete', onclick: () => onAction('delete') }, '✕')
43
+ ) : null
44
+ );
45
+ }
46
+
47
+ export function FileGrid({ files = [], onOpen, onAction, emptyText = 'no files here yet' } = {}) {
48
+ if (!files.length) return EmptyState({ text: emptyText });
49
+ return h('div', { class: 'ds-file-grid' },
50
+ ...files.map((f, i) => FileRow({
51
+ key: f.path || f.name + i,
52
+ name: f.name,
53
+ type: f.type,
54
+ size: f.size,
55
+ modified: f.modified,
56
+ code: f.code,
57
+ active: f.active,
58
+ onOpen: onOpen ? () => onOpen(f) : null,
59
+ onAction: onAction ? (act) => onAction(act, f) : null
60
+ }))
61
+ );
62
+ }
63
+
64
+ export function FileToolbar({ left = [], right = [] } = {}) {
65
+ return h('div', { class: 'ds-file-toolbar' },
66
+ h('div', { class: 'ds-file-toolbar-left' }, ...left),
67
+ h('div', { class: 'ds-file-toolbar-right' }, ...right)
68
+ );
69
+ }
70
+
71
+ export function DropZone({ children, dragover, onDrop, onDragOver, onDragLeave, label = 'drop files here', onPick } = {}) {
72
+ return h('div', {
73
+ class: 'ds-dropzone' + (dragover ? ' dragover' : ''),
74
+ ondragover: (e) => { e.preventDefault(); onDragOver && onDragOver(e); },
75
+ ondragleave: (e) => { onDragLeave && onDragLeave(e); },
76
+ ondrop: (e) => { e.preventDefault(); onDrop && onDrop(e.dataTransfer.files); }
77
+ },
78
+ h('div', { class: 'ds-dropzone-inner' },
79
+ h('span', { class: 'ds-dropzone-glyph' }, '⇪'),
80
+ h('span', { class: 'ds-dropzone-label' }, label),
81
+ onPick ? Btn({ onClick: onPick, children: 'pick files' }) : null
82
+ ),
83
+ ...(Array.isArray(children) ? children : children ? [children] : [])
84
+ );
85
+ }
86
+
87
+ export function UploadProgress({ items = [] } = {}) {
88
+ if (!items.length) return null;
89
+ return h('div', { class: 'ds-upload-progress' },
90
+ ...items.map((it, i) => h('div', {
91
+ key: it.name + i,
92
+ class: 'ds-upload-item' + (it.done ? ' done' : '') + (it.error ? ' error' : '')
93
+ },
94
+ h('span', { class: 'ds-upload-name' }, it.name),
95
+ h('span', { class: 'ds-upload-bar' },
96
+ h('span', {
97
+ class: 'ds-upload-fill',
98
+ 'data-pct': String(Math.max(0, Math.min(100, it.pct || 0)))
99
+ })
100
+ ),
101
+ h('span', { class: 'ds-upload-pct' }, (it.error ? 'err' : (it.done ? 'ok' : (it.pct || 0) + '%')))
102
+ ))
103
+ );
104
+ }
105
+
106
+ export function EmptyState({ text = 'nothing here', glyph = '◌' } = {}) {
107
+ return h('div', { class: 'ds-file-empty' },
108
+ h('span', { class: 'ds-file-empty-glyph' }, glyph),
109
+ h('span', { class: 'ds-file-empty-text' }, text)
110
+ );
111
+ }
112
+
113
+ export function BreadcrumbPath({ segments = [], onNav, root = 'root' } = {}) {
114
+ const parts = [
115
+ h('button', { key: 'root', class: 'ds-crumb-seg', onclick: () => onNav && onNav(0) }, root)
116
+ ];
117
+ segments.forEach((seg, i) => {
118
+ parts.push(h('span', { key: 'sep' + i, class: 'ds-crumb-sep' }, '›'));
119
+ parts.push(h('button', {
120
+ key: 'seg' + i,
121
+ class: 'ds-crumb-seg' + (i === segments.length - 1 ? ' leaf' : ''),
122
+ onclick: () => onNav && onNav(i + 1)
123
+ }, seg));
124
+ });
125
+ return h('div', { class: 'ds-crumb-path' }, ...parts);
126
+ }
package/src/components.js CHANGED
@@ -19,3 +19,14 @@ export {
19
19
  ChatMessage, ChatComposer, Chat,
20
20
  AICAT_FACE, AICatPortrait, AICat
21
21
  } from './components/chat.js';
22
+
23
+ export {
24
+ fileGlyph, fmtFileSize,
25
+ FileIcon, FileRow, FileGrid, FileToolbar,
26
+ DropZone, UploadProgress, EmptyState, BreadcrumbPath
27
+ } from './components/files.js';
28
+
29
+ export {
30
+ ConfirmDialog, PromptDialog,
31
+ FilePreviewMedia, FilePreviewCode, FilePreviewText, FileViewer
32
+ } from './components/files-modals.js';
package/src/highlight.js CHANGED
@@ -1,60 +1,18 @@
1
1
  import { register } from './debug.js';
2
2
 
3
- const PRISM_BASE = 'https://cdn.jsdelivr.net/npm/prismjs@1.30.0';
4
- const LANGS = ['markup', 'css', 'clike', 'javascript', 'jsx', 'tsx', 'typescript', 'json', 'bash', 'python'];
5
- let _prism = null;
6
- let _stats = { highlights: 0, errors: 0 };
3
+ let _stats = { highlights: 0 };
7
4
 
8
- function injectScript(src) {
9
- return new Promise((resolve, reject) => {
10
- const s = document.createElement('script');
11
- s.src = src; s.async = false;
12
- s.onload = () => resolve();
13
- s.onerror = () => reject(new Error('script failed: ' + src));
14
- document.head.appendChild(s);
15
- });
16
- }
17
-
18
- let _loadPromise = null;
19
5
  export function ensurePrism() {
20
- if (_prism) return Promise.resolve(_prism);
21
- if (_loadPromise) return _loadPromise;
22
- _loadPromise = (async () => {
23
- if (!window.Prism) {
24
- window.Prism = window.Prism || { manual: true, disableWorkerMessageHandler: true };
25
- await injectScript(PRISM_BASE + '/prism.min.js');
26
- }
27
- for (const lang of LANGS) {
28
- const has = window.Prism && window.Prism.languages && window.Prism.languages[lang];
29
- if (has) continue;
30
- try { await injectScript(`${PRISM_BASE}/components/prism-${lang}.min.js`); }
31
- catch { _stats.errors += 1; }
32
- }
33
- _prism = window.Prism;
34
- return _prism;
35
- })();
36
- return _loadPromise;
6
+ return Promise.resolve(null);
37
7
  }
38
8
 
39
9
  export async function highlightElement(el) {
40
- const prism = await ensurePrism();
41
- if (!el) return;
42
- prism.highlightElement(el);
43
10
  _stats.highlights += 1;
44
11
  }
45
12
 
46
13
  export async function highlightAllUnder(root) {
47
- const prism = await ensurePrism();
48
14
  const els = (root || document).querySelectorAll('pre code[class*="lang-"], pre code[class*="language-"]');
49
- els.forEach((el) => {
50
- const cls = el.className;
51
- if (/lang-(\w+)/.test(cls) && !/language-/.test(cls)) {
52
- const m = cls.match(/lang-(\w+)/);
53
- if (m) el.classList.add('language-' + m[1]);
54
- }
55
- prism.highlightElement(el);
56
- _stats.highlights += 1;
57
- });
15
+ _stats.highlights += els.length;
58
16
  }
59
17
 
60
- register('highlight', () => ({ loaded: !!_prism, langs: _prism ? Object.keys(_prism.languages || {}) : [], ...(_stats) }));
18
+ register('highlight', () => ({ loaded: false, ...(_stats) }));
package/src/motion.js CHANGED
@@ -1,122 +1,22 @@
1
- const ANIMATE_CSS_ID = 'animate-style-cdn';
2
- const ANIMATE_CSS_HREF = 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css';
3
- const MOTION_STYLE_ID = 'ds-247420-motion';
4
-
5
1
  function hasDom() {
6
2
  return typeof document !== 'undefined';
7
3
  }
8
4
 
9
5
  export function shouldReduceMotion() {
10
- if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;
11
- return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
6
+ return true;
12
7
  }
13
8
 
14
9
  export function installMotion() {
15
- if (!hasDom()) return;
16
-
17
- if (!document.getElementById(ANIMATE_CSS_ID)) {
18
- const link = document.createElement('link');
19
- link.id = ANIMATE_CSS_ID;
20
- link.rel = 'stylesheet';
21
- link.href = ANIMATE_CSS_HREF;
22
- document.head.appendChild(link);
23
- }
24
-
25
- if (!document.getElementById(MOTION_STYLE_ID)) {
26
- const style = document.createElement('style');
27
- style.id = MOTION_STYLE_ID;
28
- style.textContent = `
29
- :root {
30
- --motion-fast: 220ms;
31
- --motion-base: 420ms;
32
- --motion-slow: 720ms;
33
- }
34
-
35
- @media (prefers-reduced-motion: reduce) {
36
- .animate__animated {
37
- animation-duration: 1ms !important;
38
- animation-iteration-count: 1 !important;
39
- transition-duration: 1ms !important;
40
- }
41
- }
42
- `.trim();
43
- document.head.appendChild(style);
44
- }
45
10
  }
46
11
 
47
- export function animateElement(el, name, {
48
- duration = null,
49
- delay = null,
50
- speedClass = '',
51
- repeat = null,
52
- cleanup = true
53
- } = {}) {
54
- if (!el || !name || shouldReduceMotion()) return Promise.resolve(false);
55
-
56
- const classes = ['animate__animated', `animate__${name}`];
57
- if (speedClass) classes.push(`animate__${speedClass}`);
58
-
59
- el.classList.remove(...classes);
60
- void el.offsetWidth;
61
- el.classList.add(...classes);
62
-
63
- if (duration) el.style.setProperty('--animate-duration', duration);
64
- if (delay) el.style.setProperty('--animate-delay', delay);
65
- if (repeat != null) el.style.setProperty('--animate-repeat', String(repeat));
66
-
67
- return new Promise((resolve) => {
68
- const onEnd = () => {
69
- if (cleanup) {
70
- el.classList.remove(...classes);
71
- }
72
- if (duration) el.style.removeProperty('--animate-duration');
73
- if (delay) el.style.removeProperty('--animate-delay');
74
- if (repeat != null) el.style.removeProperty('--animate-repeat');
75
- resolve(true);
76
- };
77
- el.addEventListener('animationend', onEnd, { once: true });
78
- });
12
+ export function animateElement(el, name, opts = {}) {
13
+ return Promise.resolve(false);
79
14
  }
80
15
 
81
16
  export function animateSelector(selector, name, opts = {}) {
82
- if (!hasDom()) return Promise.resolve(false);
83
- const el = document.querySelector(selector);
84
- return animateElement(el, name, opts);
85
- }
86
-
87
- function defaultEffectFor(el) {
88
- const tag = String(el.tagName || '').toLowerCase();
89
- if (tag === 'aside') return 'fadeInLeft';
90
- if (tag === 'header') return 'fadeInDown';
91
- if (tag === 'footer') return 'fadeInUp';
92
- if (tag === 'main' || tag === 'section' || tag === 'article') return 'fadeIn';
93
- if (tag === 'a' || tag === 'button' || tag === 'input' || tag === 'textarea' || tag === 'select') return 'fadeInUp';
94
- return 'fadeIn';
17
+ return Promise.resolve(false);
95
18
  }
96
19
 
97
- export function animateTree(root, {
98
- selector = '*',
99
- baseDelayMs = 14,
100
- duration = 'var(--motion-base)'
101
- } = {}) {
102
- if (!hasDom() || !root || shouldReduceMotion()) return 0;
103
-
104
- const nodes = Array.from(root.querySelectorAll(selector));
105
- let animated = 0;
106
-
107
- nodes.forEach((el) => {
108
- if (!el || !el.classList) return;
109
- if (el.matches('script,style,link,meta,title')) return;
110
- if (el.hasAttribute('data-no-motion')) return;
111
- if (el.dataset.motionApplied === '1') return;
112
-
113
- const effect = el.dataset.motionEffect || defaultEffectFor(el);
114
- el.classList.add('animate__animated', `animate__${effect}`);
115
- el.style.setProperty('--animate-duration', duration);
116
- el.style.setProperty('--animate-delay', `${animated * baseDelayMs}ms`);
117
- el.dataset.motionApplied = '1';
118
- animated += 1;
119
- });
120
-
121
- return animated;
20
+ export function animateTree(root, opts = {}) {
21
+ return 0;
122
22
  }