@ziyarago/ui 0.3.0 → 0.5.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/CHANGELOG.md +12 -0
- package/README.md +23 -2
- package/dist/llms-full.txt +32 -3
- package/dist/llms.txt +3 -2
- package/dist/manifest.json +123 -6
- package/dist/style.css +41 -0
- package/package.json +2 -2
- package/src/core/components.js +15 -14
- package/src/core/components2.js +37 -36
- package/src/core/components3.js +29 -7
- package/src/core/components4.js +23 -22
- package/src/core/components6.js +8 -7
- package/src/core/components7.js +10 -9
- package/src/core/index.js +1 -1
- package/src/core/pages.js +1 -0
- package/src/i18n/components/ActionCard.js +5 -0
- package/src/i18n/components/Actionsheet.js +5 -0
- package/src/i18n/components/Alert.js +5 -0
- package/src/i18n/components/Breadcrumbs.js +5 -0
- package/src/i18n/components/Calendar.js +5 -0
- package/src/i18n/components/CallCard.js +5 -0
- package/src/i18n/components/CallRow.js +5 -0
- package/src/i18n/components/Carousel.js +5 -0
- package/src/i18n/components/ChartCard.js +5 -0
- package/src/i18n/components/ChatAi.js +5 -0
- package/src/i18n/components/Chip.js +5 -0
- package/src/i18n/components/ChipInput.js +5 -0
- package/src/i18n/components/CodeInput.js +5 -0
- package/src/i18n/components/Combobox.js +5 -0
- package/src/i18n/components/CommandPalette.js +5 -0
- package/src/i18n/components/ConfirmDialog.js +5 -0
- package/src/i18n/components/ContactPanel.js +5 -0
- package/src/i18n/components/CopyButton.js +2 -0
- package/src/i18n/components/DataGroup.js +5 -0
- package/src/i18n/components/DataState.js +5 -0
- package/src/i18n/components/DataTable.js +5 -0
- package/src/i18n/components/DatePicker.js +5 -0
- package/src/i18n/components/DealCard.js +5 -0
- package/src/i18n/components/Drawer.js +5 -0
- package/src/i18n/components/ErrorPage.js +5 -0
- package/src/i18n/components/FileUpload.js +5 -0
- package/src/i18n/components/FullscreenDialog.js +5 -0
- package/src/i18n/components/Gallery.js +5 -0
- package/src/i18n/components/GuestCard.js +5 -0
- package/src/i18n/components/ImageUpload.js +5 -0
- package/src/i18n/components/ImageViewer.js +5 -0
- package/src/i18n/components/IncomingCall.js +5 -0
- package/src/i18n/components/InlineEdit.js +5 -0
- package/src/i18n/components/IntegrationCard.js +5 -0
- package/src/i18n/components/LoginForm.js +5 -0
- package/src/i18n/components/Map.js +5 -0
- package/src/i18n/components/Modal.js +5 -0
- package/src/i18n/components/MultiSelect.js +5 -0
- package/src/i18n/components/NotificationBell.js +5 -0
- package/src/i18n/components/NumberInput.js +5 -0
- package/src/i18n/components/Pagination.js +5 -0
- package/src/i18n/components/PasswordInput.js +5 -0
- package/src/i18n/components/Popconfirm.js +5 -0
- package/src/i18n/components/PricingCard.js +5 -0
- package/src/i18n/components/RamadanTracker.js +5 -0
- package/src/i18n/components/RangeCalendar.js +5 -0
- package/src/i18n/components/RangeSlider.js +5 -0
- package/src/i18n/components/Rating.js +5 -0
- package/src/i18n/components/RichEditor.js +5 -0
- package/src/i18n/components/Screensaver.js +5 -0
- package/src/i18n/components/SearchInput.js +5 -0
- package/src/i18n/components/SideNav.js +5 -0
- package/src/i18n/components/Snackbar.js +5 -0
- package/src/i18n/components/Sortable.js +5 -0
- package/src/i18n/components/Spinner.js +5 -0
- package/src/i18n/components/StatusPage.js +5 -0
- package/src/i18n/components/StepDialog.js +5 -0
- package/src/i18n/components/StepForm.js +5 -0
- package/src/i18n/components/TabTiles.js +5 -0
- package/src/i18n/components/Tag.js +5 -0
- package/src/i18n/components/TopNav.js +5 -0
- package/src/i18n/components/Tour.js +5 -0
- package/src/i18n/components/TourCard.js +5 -0
- package/src/i18n/components/TourPopover.js +5 -0
- package/src/i18n/components/TreeSelect.js +5 -0
- package/src/i18n/components/Validation.js +5 -0
- package/src/i18n/components/index.js +130 -0
- package/src/i18n/index.js +8 -6
- package/src/meta/domain.js +20 -0
- package/src/meta/groups.js +1 -1
- package/src/meta/pages.js +9 -1
- package/src/meta/templates.json +1 -1
- package/src/react/index.js +1 -0
- package/src/styles/components8.css +41 -0
- package/src/vue/index.js +1 -1
- package/types/i18n.d.ts +4 -2
- package/types/react.d.ts +80 -2
- package/types/vue-global.d.ts +1 -0
- package/types/vue.d.ts +83 -2
package/src/core/components6.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// @ziyarago/ui · components, part 6 — last catalog gaps: TreeSelect, ContextMenu, Sortable, Map, Screensaver, ImageUpload, Tour.
|
|
2
|
+
import { t } from '../i18n/index.js';
|
|
2
3
|
import { icon, cx, ddRef } from './components.js';
|
|
3
4
|
import { trap, life } from './dialog.js';
|
|
4
5
|
const clamp = (v, a, b) => Math.max(a, Math.min(b, v));
|
|
@@ -10,7 +11,7 @@ export const more6 = {
|
|
|
10
11
|
if (q && !all.filter(x => x.label.toLowerCase().includes(q)).some(x => x.id === n.id || (n.children || []).some(function f(c) { return c.id === x.id || (c.children || []).some(f); }))) return null;
|
|
11
12
|
return h('div', { key: n.id }, h('button', { type: 'button', role: 'treeitem', disabled: n.disabled, 'aria-disabled': n.disabled ? 'true' : undefined, class: cx('zg-tree__n', n.id === p.modelValue && 'zg-tree__n--on'), style: { paddingInlineStart: 8 + d * 18 + 'px', width: '100%' }, onClick: () => { if (has && !q) set({ ex: { ...state.ex, [n.id]: !o } }); if (!has || p.selectGroups) { set({ open: false, q: '' }); p.onChange && p.onChange(n.id); } } }, has ? icon(h, o ? 'chevron-down' : 'chevron-right', 14) : h('span', { style: { width: '14px' } }), n.label), has && o ? n.children.map(c => node(c, d + 1)) : null); };
|
|
12
13
|
return h('div', { class: 'zg-field' }, p.label ? h('span', { class: 'zg-label' }, p.label) : null, h('div', { class: 'zg-select' }, h('button', { type: 'button', class: 'zg-btn zg-select__trigger', 'aria-haspopup': 'tree', 'aria-expanded': String(state.open && !p.disabled), disabled: p.disabled, style: { height: 'var(--zg-h-lg)' }, onClick: () => set({ open: !state.open }) }, h('span', null, cur ? cur.label : (p.placeholder || '—')), icon(h, 'chevron-down', 16)),
|
|
13
|
-
state.open && !p.disabled ? h('div', { class: 'zg-select__list', role: 'tree', 'data-zg-dd': '', ref: ddRef(() => set({ open: false, q: '' })), style: { padding: '8px' } }, h('span', { class: 'zg-input', style: { '--h': '36px', marginBottom: '6px' } }, icon(h, 'search', 14), h('input', { value: state.q, placeholder: '
|
|
14
|
+
state.open && !p.disabled ? h('div', { class: 'zg-select__list', role: 'tree', 'data-zg-dd': '', ref: ddRef(() => set({ open: false, q: '' })), style: { padding: '8px' } }, h('span', { class: 'zg-input', style: { '--h': '36px', marginBottom: '6px' } }, icon(h, 'search', 14), h('input', { value: state.q, placeholder: t('TreeSelect', 'search'), onInput: e => set({ q: e.target.value }) })), ...(p.nodes || []).map(n => node(n, 0))) : null)); } },
|
|
14
15
|
ContextMenu: { state: { x: 0, y: 0, open: false }, render: ({ h, props: p, state, set, children }) => {
|
|
15
16
|
const close = () => set({ open: false });
|
|
16
17
|
return h('div', { class: 'zg-ctx', onContextmenu: e => { e.preventDefault(); set({ open: true, x: e.clientX, y: e.clientY }); } }, ...children,
|
|
@@ -19,7 +20,7 @@ export const more6 = {
|
|
|
19
20
|
const drop = (to, f) => { const from = f === undefined ? state.drag : f; set({ drag: null, over: null }); if (from == null || from === to) return; const a = items.slice(); const [m] = a.splice(from, 1); a.splice(to, 0, m); p.onChange && p.onChange(a); };
|
|
20
21
|
return h('div', { class: 'zg-sort', role: 'list' }, ...items.map((it, i) => h('div', { key: it.id ?? i, role: 'listitem', class: cx('zg-sort__i', state.over === i && state.drag !== i && 'is-over', state.drag === i && 'is-drag'), draggable: 'true', onDragstart: e => { e.dataTransfer.effectAllowed = 'move'; try { e.dataTransfer.setData('text/plain', String(i)); } catch (x) {} set({ drag: i }); }, onDragover: e => { e.preventDefault(); if (state.over !== i) set({ over: i }); }, onDrop: e => { e.preventDefault(); drop(i); }, onDragend: () => set({ drag: null, over: null }) },
|
|
21
22
|
h('span', { class: 'zg-sort__h', 'aria-hidden': 'true' }, icon(h, 'grip-vertical', 16)), h('div', { style: { flex: 1, minWidth: 0 } }, p.render ? p.render(it, i) : h('b', null, it.label)),
|
|
22
|
-
h('span', { style: { display: 'flex', gap: '2px' } }, h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--sm zg-ibtn--ghost', 'aria-label': '
|
|
23
|
+
h('span', { style: { display: 'flex', gap: '2px' } }, h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--sm zg-ibtn--ghost', 'aria-label': t('Sortable', 'moveUp'), disabled: i === 0, onClick: () => drop(i - 1, i) }, icon(h, 'chevron-up', 14)), h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--sm zg-ibtn--ghost', 'aria-label': t('Sortable', 'moveDown'), disabled: i === items.length - 1, onClick: () => drop(i + 1, i) }, icon(h, 'chevron-down', 14)))))); } },
|
|
23
24
|
Map: { state: { lon: null, lat: null, z: null, dk: null, w: null }, render: ({ h, props: p, state, set }) => {
|
|
24
25
|
const W = state.w || p.width || 640, H = p.height || 360, z = state.z ?? p.zoom ?? 14, lat0 = state.lat ?? p.lat ?? 21.4225, lon0 = state.lon ?? p.lon ?? 39.8262, n = 2 ** z;
|
|
25
26
|
const mpx = (lat, lon, nn) => [(lon + 180) / 360 * nn * 256, (1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * nn * 256], px = (lat, lon) => mpx(lat, lon, n);
|
|
@@ -35,23 +36,23 @@ export const more6 = {
|
|
|
35
36
|
el.addEventListener('pointermove', mv); el.addEventListener('pointerup', up); el.addEventListener('pointercancel', up); };
|
|
36
37
|
const mk = (p.markers || []).map((m, i) => { const [mx, my] = px(m.lat, m.lon); return h('button', { key: 'm' + i, type: 'button', class: cx('zg-pin', m.tone && 'zg-t-' + m.tone), title: m.label, style: { left: (mx - x0) + 'px', top: (my - y0) + 'px' }, onClick: () => p.onSelect && p.onSelect(m) }, icon(h, m.icon || 'map-pin', 16)); });
|
|
37
38
|
const stop = e => e.stopPropagation(), zb = (dz, k, d, ic) => h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--sm', 'aria-label': (p.labels && p.labels[k]) || d, onPointerdown: stop, onDblclick: stop, onClick: () => zoomAt(dz, 0, 0) }, icon(h, ic, 16));
|
|
38
|
-
return h('div', { class: 'zg-map', role: 'application', 'aria-label': p.label || 'Map', style: { height: H + 'px' }, onPointerdown: pan, onDblclick: e => { const [ox, oy] = rel(e, e.currentTarget); zoomAt(1, ox, oy); },
|
|
39
|
+
return h('div', { class: 'zg-map', role: 'application', 'aria-label': p.label || t('Map', 'label'), style: { height: H + 'px' }, onPointerdown: pan, onDblclick: e => { const [ox, oy] = rel(e, e.currentTarget); zoomAt(1, ox, oy); },
|
|
39
40
|
ref: el => { if (!el) return; el.__zgw = e => { e.preventDefault(); const t = Date.now(); if (t - (el.__zgt || 0) < 180) return; el.__zgt = t; const [ox, oy] = rel(e, el); zoomAt(e.deltaY < 0 ? 1 : -1, ox, oy); };
|
|
40
41
|
if (!el.__zgi) { el.__zgi = 1; el.addEventListener('wheel', e => el.__zgw(e), { passive: false }); if (typeof ResizeObserver !== 'undefined') new ResizeObserver(() => { const w = Math.round(el.clientWidth); if (w && w !== el.__zgl) { el.__zgl = w; set({ w }); } }).observe(el); }
|
|
41
42
|
if (p.theme == null && state.dk == null) set({ dk: !!el.closest('[data-theme="dark"]') }); } }, ...tiles, ...mk,
|
|
42
|
-
h('div', { class: 'zg-map__z' }, zb(1, 'zoomIn', '
|
|
43
|
+
h('div', { class: 'zg-map__z' }, zb(1, 'zoomIn', t('Map', 'zoomIn'), 'plus'), zb(-1, 'zoomOut', t('Map', 'zoomOut'), 'minus')),
|
|
43
44
|
h('span', { class: 'zg-map__c' }, '© OpenStreetMap · CARTO')); } },
|
|
44
45
|
ImageUpload: { state: { src: null }, render: ({ h, props: p, state, set }) => { const src = state.src || p.modelValue, round = p.shape === 'circle';
|
|
45
|
-
return h('div', { class: 'zg-field' }, p.label ? h('span', { class: 'zg-label' }, p.label) : null, h('label', { class: 'zg-imgup', style: { aspectRatio: p.aspect || '1/1', maxWidth: (({ xs: 112, sm: 128, md: 160, lg: 192, xl: 224 })[p.size] || p.size || 160) + 'px', borderRadius: round ? '50%' : '24px', backgroundImage: src ? `url(${src})` : undefined } }, src ? null : h('span', { class: 'zg-imgup__e' }, icon(h, 'image-up', 24), h('span', { class: 'zg-hint' }, p.hint || '
|
|
46
|
+
return h('div', { class: 'zg-field' }, p.label ? h('span', { class: 'zg-label' }, p.label) : null, h('label', { class: 'zg-imgup', style: { aspectRatio: p.aspect || '1/1', maxWidth: (({ xs: 112, sm: 128, md: 160, lg: 192, xl: 224 })[p.size] || p.size || 160) + 'px', borderRadius: round ? '50%' : '24px', backgroundImage: src ? `url(${src})` : undefined } }, src ? null : h('span', { class: 'zg-imgup__e' }, icon(h, 'image-up', 24), h('span', { class: 'zg-hint' }, p.hint || t('ImageUpload', 'upload'))), h('span', { class: 'zg-imgup__o' }, icon(h, 'camera', 18)),
|
|
46
47
|
h('input', { type: 'file', accept: 'image/*', style: { display: 'none' }, onChange: e => { const f = e.target.files[0]; if (!f) return; const r = new FileReader(); r.onload = () => { set({ src: r.result }); p.onChange && p.onChange(r.result, f); }; r.readAsDataURL(f); } }))); } },
|
|
47
48
|
Screensaver: { state: { t: 0 }, render: ({ h, props: p, state, set }) => { if (!p.open) return p.idleMs > 0 ? h('span', { hidden: true, 'aria-hidden': 'true', ref: life({ idleMs: p.idleMs, onIdle: p.onIdle, mount: (el, get) => { let tm; const arm = () => { clearTimeout(tm); tm = setTimeout(() => { const o = get(); o.onIdle && o.onIdle(); }, get().idleMs); }, evs = ['pointermove', 'pointerdown', 'keydown', 'wheel', 'touchstart']; evs.forEach(e => document.addEventListener(e, arm, { passive: true })); arm(); return () => { clearTimeout(tm); evs.forEach(e => document.removeEventListener(e, arm)); }; } }) }) : null;
|
|
48
49
|
const d = new Date(state.t || 0), pad = n => String(n).padStart(2, '0'), ph = (d.getSeconds() % 40) / 40;
|
|
49
|
-
return h('div', { class: 'zg-saver', role: 'dialog', 'aria-modal': 'true', 'aria-label': 'Screensaver', tabIndex: 0, ref: trap({ onClose: p.onClose, onKey: e => { if (e.key === 'Tab') return false; p.onClose && p.onClose(); return true; }, mount: el => { const id = setInterval(() => set({ t: Date.now() }), 1000); set({ t: Date.now() }); return () => clearInterval(id); } }), onClick: p.onClose }, h('span', { class: 'zg-saver__g', style: { left: (10 + ph * 60) + '%', top: (20 + Math.sin(ph * 6.28) * 18) + '%' } }),
|
|
50
|
+
return h('div', { class: 'zg-saver', role: 'dialog', 'aria-modal': 'true', 'aria-label': t('Screensaver', 'label'), tabIndex: 0, ref: trap({ onClose: p.onClose, onKey: e => { if (e.key === 'Tab') return false; p.onClose && p.onClose(); return true; }, mount: el => { const id = setInterval(() => set({ t: Date.now() }), 1000); set({ t: Date.now() }); return () => clearInterval(id); } }), onClick: p.onClose }, h('span', { class: 'zg-saver__g', style: { left: (10 + ph * 60) + '%', top: (20 + Math.sin(ph * 6.28) * 18) + '%' } }),
|
|
50
51
|
h('div', { class: 'zg-saver__c' }, h('span', { class: 'zg-saver__m', style: { backgroundImage: 'url(assets/brand/ziyarago-mark.svg)' } }), h('b', { class: 'zg-num', style: { fontSize: 'clamp(64px,12vw,160px)', fontWeight: 200, letterSpacing: '-.04em', lineHeight: 1 } }, state.t ? pad(d.getHours()) + ':' + pad(d.getMinutes()) : '--:--'), h('span', { style: { color: 'var(--zg-text-2)', fontSize: '18px' } }, state.t ? new Intl.DateTimeFormat(p.locale || 'en-GB', { weekday: 'long', day: 'numeric', month: 'long' }).format(d) : '\u00a0'), p.hint ? h('span', { class: 'zg-hint' }, p.hint) : null)); } },
|
|
51
52
|
Tour: { state: { i: 0, r: null }, render: ({ C, h, props: p, state, set }) => { if (!p.open) return null; const st = p.steps || [], i = clamp(p.step != null ? p.step : state.i, 0, Math.max(0, st.length - 1)), s = st[i] || {};
|
|
52
53
|
const measure = () => { if (state.r || state.busy || !s.target) return; const el0 = document.querySelector(s.target); if (!el0) return; state.busy = true; setTimeout(() => { const el = document.querySelector(s.target) || el0, q = el.getBoundingClientRect(); if (q.top < 80 || q.bottom > innerHeight - 220) { let a = el.parentElement; while (a && !(/(auto|scroll)/.test(getComputedStyle(a).overflowY) && a.scrollHeight > a.clientHeight + 4)) a = a.parentElement; const dy = q.top - innerHeight / 3; if (a) a.scrollTop += dy; else window.scrollTo(0, window.scrollY + dy); } setTimeout(() => { state.busy = false; set({ r: (document.querySelector(s.target) || el).getBoundingClientRect() }); }, 160); }, 0); };
|
|
53
54
|
const r = state.r, pad = 8, below = r ? r.bottom + 12 + 190 < innerHeight : true;
|
|
54
55
|
const go = d => { const n = clamp(i + d, 0, st.length - 1); if (n === i) return; set({ i: n, r: null }); p.onStep && p.onStep(n); }, done = () => { set({ i: 0, r: null }); p.onClose && p.onClose(); };
|
|
55
|
-
return h('div', { class: 'zg-tourov', role: 'dialog', 'aria-label': 'Tour', ref: el => { if (el) measure(); trap({ focus: false, onClose: done, mount: () => () => set({ i: 0, r: null }), onKey: e => { const rtl = document.documentElement.dir === 'rtl', k = e.key === 'ArrowRight' ? (rtl ? -1 : 1) : e.key === 'ArrowLeft' ? (rtl ? 1 : -1) : 0; if (k) { e.preventDefault(); go(k); return true; } } })(el); } }, r ? h('span', { class: 'zg-tourov__cut', style: { left: (r.left - pad) + 'px', top: (r.top - pad) + 'px', width: (r.width + pad * 2) + 'px', height: (r.height + pad * 2) + 'px' } }) : h('span', { class: 'zg-tourov__full' }),
|
|
56
|
+
return h('div', { class: 'zg-tourov', role: 'dialog', 'aria-label': t('Tour', 'label'), ref: el => { if (el) measure(); trap({ focus: false, onClose: done, mount: () => () => set({ i: 0, r: null }), onKey: e => { const rtl = document.documentElement.dir === 'rtl', k = e.key === 'ArrowRight' ? (rtl ? -1 : 1) : e.key === 'ArrowLeft' ? (rtl ? 1 : -1) : 0; if (k) { e.preventDefault(); go(k); return true; } } })(el); } }, r ? h('span', { class: 'zg-tourov__cut', style: { left: (r.left - pad) + 'px', top: (r.top - pad) + 'px', width: (r.width + pad * 2) + 'px', height: (r.height + pad * 2) + 'px' } }) : h('span', { class: 'zg-tourov__full' }),
|
|
56
57
|
h('div', { style: { position: 'fixed', zIndex: 2, left: r ? clamp(r.left, 12, innerWidth - 392) + 'px' : '50%', top: r ? (below ? r.bottom + 12 : Math.max(12, r.top - 12 - 190)) + 'px' : '40%', transform: r ? 'none' : 'translateX(-50%)' } }, h(C.TourPopover, { title: s.title, text: s.text, step: (i + 1) + ' / ' + st.length, last: i === st.length - 1, onBack: i ? () => go(-1) : null, onNext: () => i === st.length - 1 ? done() : go(1), onClose: done }))); } }
|
|
57
58
|
};
|
package/src/core/components7.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// @ziyarago/ui · components, part 7 — gluestack parity: typography, layout primitives, Link, Pressable, Icon, Portal, sheets, ImageViewer, ChatAi, LiquidGlass.
|
|
2
|
+
import { t } from '../i18n/index.js';
|
|
2
3
|
import { icon, cx } from './components.js';
|
|
3
4
|
import { trap } from './dialog.js';
|
|
4
5
|
const clamp = (v, a, b) => Math.max(a, Math.min(b, v));
|
|
@@ -22,21 +23,21 @@ export const more7 = {
|
|
|
22
23
|
h('span', { class: 'zg-sheet__grab', 'aria-hidden': 'true' }), p.title ? h('h3', { class: 'zg-sheet__t' }, p.title) : null, h('div', { class: 'zg-sheet__b' }, ...children), (slots.footer || p.footer) ? h('div', { class: 'zg-sheet__f' }, slots.footer || p.footer) : null)) },
|
|
23
24
|
Actionsheet: { render: ({ C, h, props: p }) => h(C.BottomSheet, { open: p.open, size: p.size, onClose: p.onClose, title: p.title },
|
|
24
25
|
h('div', { class: 'zg-as' }, ...(p.items || []).map((it, i) => h('button', { key: i, type: 'button', class: cx('zg-as__i', it.tone && 'zg-as__i--' + it.tone), disabled: it.disabled, onClick: () => { it.onClick && it.onClick(); p.onSelect && p.onSelect(it); p.onClose && p.onClose(); } }, it.icon ? icon(h, it.icon, 18) : null, h('span', null, it.label)))),
|
|
25
|
-
h('button', { type: 'button', class: 'zg-as__i zg-as__i--cancel', onClick: p.onClose }, p.cancelLabel || '
|
|
26
|
+
h('button', { type: 'button', class: 'zg-as__i zg-as__i--cancel', onClick: p.onClose }, p.cancelLabel || t('Actionsheet', 'cancel'))) },
|
|
26
27
|
ImageViewer: { state: { i: null }, render: ({ h, props: p, state, set }) => {
|
|
27
28
|
if (!p.open) return null;
|
|
28
29
|
const im = p.images || [], i = clamp(state.i ?? p.index ?? 0, 0, Math.max(0, im.length - 1)), go = d => set({ i: (i + d + im.length) % im.length });
|
|
29
|
-
return h('div', { class: 'zg-iv', role: 'dialog', 'aria-modal': 'true', 'aria-label': p.alt || '
|
|
30
|
-
h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--ghost zg-iv__x', 'aria-label': '
|
|
31
|
-
im.length > 1 ? h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--ghost zg-iv__p', 'aria-label': '
|
|
30
|
+
return h('div', { class: 'zg-iv', role: 'dialog', 'aria-modal': 'true', 'aria-label': p.alt || t('ImageViewer', 'label'), onClick: p.onClose },
|
|
31
|
+
h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--ghost zg-iv__x', 'aria-label': t('ImageViewer', 'close'), onClick: p.onClose }, icon(h, 'x', 20)),
|
|
32
|
+
im.length > 1 ? h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--ghost zg-iv__p', 'aria-label': t('ImageViewer', 'previous'), onClick: e => { e.stopPropagation(); go(-1); } }, icon(h, 'chevron-left', 22)) : null,
|
|
32
33
|
h('img', { class: 'zg-iv__img', src: im[i], alt: p.alt || '', onClick: e => e.stopPropagation() }),
|
|
33
|
-
im.length > 1 ? h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--ghost zg-iv__n', 'aria-label': '
|
|
34
|
+
im.length > 1 ? h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--ghost zg-iv__n', 'aria-label': t('ImageViewer', 'next'), onClick: e => { e.stopPropagation(); go(1); } }, icon(h, 'chevron-right', 22)) : null,
|
|
34
35
|
h('span', { class: 'zg-badge zg-iv__c' }, `${i + 1} / ${im.length}`)); } },
|
|
35
36
|
ChatAi: { state: { q: '' }, render: ({ h, props: p, state, set }) => {
|
|
36
37
|
const send = () => { const t = state.q.trim(); if (!t || p.loading) return; set({ q: '' }); p.onSend && p.onSend(t); };
|
|
37
|
-
return h('section', { class: 'zg-chat zg-glass', 'aria-label': p.title || '
|
|
38
|
+
return h('section', { class: 'zg-chat zg-glass', 'aria-label': p.title || t('ChatAi', 'assistant') },
|
|
38
39
|
p.title ? h('div', { class: 'zg-chat__h' }, h('b', null, p.title), p.subtitle ? h('span', { class: 'zg-hint' }, p.subtitle) : null) : null,
|
|
39
|
-
h('div', { class: 'zg-chat__m', role: 'log', 'aria-live': 'polite' }, ...(p.messages || []).map((m, i) => h('div', { key: i, class: cx('zg-chat__b', 'zg-chat__b--' + (m.role === 'user' ? 'user' : 'ai')) }, m.text)), p.loading ? h('div', { class: 'zg-chat__b zg-chat__b--ai zg-chat__dots', 'aria-label': '
|
|
40
|
-
h('div', { class: 'zg-chat__f' }, h('input', { class: 'zg-chat__in', value: state.q, placeholder: p.placeholder || '
|
|
41
|
-
h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--brand', 'aria-label': '
|
|
40
|
+
h('div', { class: 'zg-chat__m', role: 'log', 'aria-live': 'polite' }, ...(p.messages || []).map((m, i) => h('div', { key: i, class: cx('zg-chat__b', 'zg-chat__b--' + (m.role === 'user' ? 'user' : 'ai')) }, m.text)), p.loading ? h('div', { class: 'zg-chat__b zg-chat__b--ai zg-chat__dots', 'aria-label': t('ChatAi', 'typing') }, h('i'), h('i'), h('i')) : null),
|
|
41
|
+
h('div', { class: 'zg-chat__f' }, h('input', { class: 'zg-chat__in', value: state.q, placeholder: p.placeholder || t('ChatAi', 'placeholder'), 'aria-label': t('ChatAi', 'message'), onInput: e => set({ q: e.target.value }), onKeydown: e => { if (e.key === 'Enter') { e.preventDefault(); send(); } } }),
|
|
42
|
+
h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--brand', 'aria-label': t('ChatAi', 'send'), disabled: p.loading || !state.q.trim(), onClick: send }, icon(h, 'send', 18)))); } },
|
|
42
43
|
};
|
package/src/core/index.js
CHANGED
|
@@ -7,5 +7,5 @@ import { more6 } from './components6.js';
|
|
|
7
7
|
import { more7 } from './components7.js';
|
|
8
8
|
export const components = { ...base, ...more, ...more3, ...more4, ...more6, ...more7, ...pages };
|
|
9
9
|
export { fmt, setIconBase, rules };
|
|
10
|
-
export { LOCALES, t, setUiLocale, getUiLocale, setUiMessages, isRtlLocale, subscribeUiLocale, getUiVersion, defineMessages } from '../i18n/index.js';
|
|
10
|
+
export { LOCALES, FREE_LOCALES, t, setUiLocale, getUiLocale, setUiMessages, isRtlLocale, subscribeUiLocale, getUiVersion, defineMessages } from '../i18n/index.js';
|
|
11
11
|
import '../i18n/components/index.js';
|
package/src/core/pages.js
CHANGED
|
@@ -42,6 +42,7 @@ const T = Object.fromEntries([
|
|
|
42
42
|
|
|
43
43
|
T.PageAuth = { slots: ['background', 'logo', 'aside', 'form', 'footer'], render: ({ C, h, props: p, slots: s }) => {
|
|
44
44
|
const body = [s.form || null, s.footer ? h('div', { class: 'zg-pg__r', 'data-slot': 'footer' }, s.footer) : null];
|
|
45
|
+
if (['photo', 'light', 'tint'].includes(p.layout)) return h(C.AuthShowcase, { variant: p.layout, title: p.title, subtitle: p.subtitle, logo: s.logo, footer: s.footer, image: p.image, headline: p.headline, caption: p.caption, quote: p.quote, chips: p.chips, people: p.people, proof: p.proof, proofHint: p.proofHint }, s.form || null);
|
|
45
46
|
return p.layout === 'split'
|
|
46
47
|
? h(C.AuthSplit, { title: p.title, subtitle: p.subtitle, logo: s.logo, aside: s.aside }, ...body)
|
|
47
48
|
: h('div', { class: 'zg-pgauth' }, s.background ? h('div', { class: 'zg-pg__r zg-pgauth__bg', 'data-slot': 'background' }, s.background) : null, h('div', { class: 'zg-pgauth__c' }, h(C.AuthLayout, { title: p.title, subtitle: p.subtitle, logo: s.logo }, ...body)));
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { expand: 'Expand', collapse: 'Collapse', refresh: 'Refresh', remove: 'Remove' },
|
|
3
|
+
ar: { expand: 'توسيع', collapse: 'طي', refresh: 'تحديث', remove: 'إزالة' },
|
|
4
|
+
ru: { expand: 'Развернуть', collapse: 'Свернуть', refresh: 'Обновить', remove: 'Удалить' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { assistant: 'Assistant', placeholder: 'Ask anything…', typing: 'Typing', message: 'Message', send: 'Send' },
|
|
3
|
+
ar: { assistant: 'المساعد', placeholder: 'اسأل أي شيء…', typing: 'يكتب', message: 'رسالة', send: 'إرسال' },
|
|
4
|
+
ru: { assistant: 'Ассистент', placeholder: 'Спросите что угодно…', typing: 'Печатает', message: 'Сообщение', send: 'Отправить' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { label: 'Command palette', placeholder: 'Type a command…', empty: 'No commands' },
|
|
3
|
+
ar: { label: 'لوحة الأوامر', placeholder: 'اكتب أمرًا…', empty: 'لا توجد أوامر' },
|
|
4
|
+
ru: { label: 'Палитра команд', placeholder: 'Введите команду…', empty: 'Нет команд' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { phone: 'Phone', telegram: 'Telegram', email: 'Email', city: 'City', call: 'Call', message: 'Message' },
|
|
3
|
+
ar: { phone: 'الهاتف', telegram: 'Telegram', email: 'البريد الإلكتروني', city: 'المدينة', call: 'اتصال', message: 'رسالة' },
|
|
4
|
+
ru: { phone: 'Телефон', telegram: 'Telegram', email: 'Email', city: 'Город', call: 'Позвонить', message: 'Написать' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { loading: 'Loading…', empty: 'Nothing here yet', error: 'Something went wrong', retry: 'Retry', offline: 'No internet', offlineDesc: 'Saved guides still work.', tryAgain: 'Try again' },
|
|
3
|
+
ar: { loading: 'جارٍ التحميل…', empty: 'لا يوجد شيء هنا بعد', error: 'حدث خطأ ما', retry: 'إعادة المحاولة', offline: 'لا يوجد اتصال بالإنترنت', offlineDesc: 'الأدلة المحفوظة ما زالت تعمل.', tryAgain: 'حاول مرة أخرى' },
|
|
4
|
+
ru: { loading: 'Загрузка…', empty: 'Пока здесь пусто', error: 'Что-то пошло не так', retry: 'Повторить', offline: 'Нет интернета', offlineDesc: 'Сохранённые путеводители по-прежнему работают.', tryAgain: 'Повторить попытку' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { title: 'Page not found', description: 'The page may have moved. Check the address or go back.' },
|
|
3
|
+
ar: { title: 'الصفحة غير موجودة', description: 'ربما تم نقل الصفحة. تحقق من العنوان أو ارجع.' },
|
|
4
|
+
ru: { title: 'Страница не найдена', description: 'Возможно, страница была перемещена. Проверьте адрес или вернитесь назад.' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { label: 'Image viewer', close: 'Close', previous: 'Previous', next: 'Next' },
|
|
3
|
+
ar: { label: 'عارض الصور', close: 'إغلاق', previous: 'السابق', next: 'التالي' },
|
|
4
|
+
ru: { label: 'Просмотр изображений', close: 'Закрыть', previous: 'Назад', next: 'Далее' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { connected: 'Connected', error: 'Error', off: 'Not linked', manage: 'Manage', reconnect: 'Reconnect', link: 'Link' },
|
|
3
|
+
ar: { connected: 'متصل', error: 'خطأ', off: 'غير مرتبط', manage: 'إدارة', reconnect: 'إعادة الاتصال', link: 'ربط' },
|
|
4
|
+
ru: { connected: 'Подключено', error: 'Ошибка', off: 'Не подключено', manage: 'Управлять', reconnect: 'Подключить снова', link: 'Подключить' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { email: 'Email or phone', password: 'Password', remember: 'Remember device', forgot: 'Forgot password?', submit: 'Sign in' },
|
|
3
|
+
ar: { email: 'البريد الإلكتروني أو الهاتف', password: 'كلمة المرور', remember: 'تذكر هذا الجهاز', forgot: 'نسيت كلمة المرور؟', submit: 'تسجيل الدخول' },
|
|
4
|
+
ru: { email: 'Email или телефон', password: 'Пароль', remember: 'Запомнить устройство', forgot: 'Забыли пароль?', submit: 'Войти' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { label: 'Pagination', prev: 'Previous page', next: 'Next page', page: 'Page' },
|
|
3
|
+
ar: { label: 'ترقيم الصفحات', prev: 'الصفحة السابقة', next: 'الصفحة التالية', page: 'صفحة' },
|
|
4
|
+
ru: { label: 'Постраничная навигация', prev: 'Предыдущая страница', next: 'Следующая страница', page: 'Страница' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { editor: 'Editor', placeholder: 'Write something…', bold: 'Bold', italic: 'Italic', underline: 'Underline', strike: 'Strike', left: 'Left', center: 'Center', right: 'Right', bullets: 'Bullets', numbers: 'Numbers', quote: 'Quote', codeBlock: 'Code block' },
|
|
3
|
+
ar: { editor: 'المحرر', placeholder: 'اكتب شيئًا…', bold: 'غامق', italic: 'مائل', underline: 'تسطير', strike: 'يتوسطه خط', left: 'يسار', center: 'وسط', right: 'يمين', bullets: 'نقاط', numbers: 'أرقام', quote: 'اقتباس', codeBlock: 'كتلة برمجية' },
|
|
4
|
+
ru: { editor: 'Редактор', placeholder: 'Напишите что-нибудь…', bold: 'Жирный', italic: 'Курсив', underline: 'Подчёркнутый', strike: 'Зачёркнутый', left: 'По левому краю', center: 'По центру', right: 'По правому краю', bullets: 'Маркированный список', numbers: 'Нумерованный список', quote: 'Цитата', codeBlock: 'Блок кода' },
|
|
5
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: { nfTitle: 'Page not found', nfDesc: 'The page may have moved. Check the address or go back.', home: 'Back to home', authTitle: 'Not authorized', authDesc: 'You need permission to open this page.', mtTitle: 'Under maintenance', mtDesc: 'We are updating the service. It will be back shortly.', soonTitle: 'Coming soon', soonDesc: 'We are working on it. Leave your email and we will tell you first.', notify: 'Notify me' },
|
|
3
|
+
ar: { nfTitle: 'الصفحة غير موجودة', nfDesc: 'ربما تم نقل الصفحة. تحقق من العنوان أو ارجع.', home: 'العودة إلى الرئيسية', authTitle: 'غير مصرح', authDesc: 'تحتاج إلى إذن لفتح هذه الصفحة.', mtTitle: 'قيد الصيانة', mtDesc: 'نقوم بتحديث الخدمة. ستعود قريبًا.', soonTitle: 'قريبًا', soonDesc: 'نعمل على ذلك. اترك بريدك الإلكتروني وسنخبرك أولًا.', notify: 'أبلغني' },
|
|
4
|
+
ru: { nfTitle: 'Страница не найдена', nfDesc: 'Возможно, страница была перемещена. Проверьте адрес или вернитесь назад.', home: 'На главную', authTitle: 'Нет доступа', authDesc: 'Для открытия этой страницы нужно разрешение.', mtTitle: 'Технические работы', mtDesc: 'Мы обновляем сервис. Скоро он снова заработает.', soonTitle: 'Скоро', soonDesc: 'Мы работаем над этим. Оставьте email, и мы сообщим вам первыми.', notify: 'Уведомить меня' },
|
|
5
|
+
};
|