@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.
Files changed (94) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +23 -2
  3. package/dist/llms-full.txt +32 -3
  4. package/dist/llms.txt +3 -2
  5. package/dist/manifest.json +123 -6
  6. package/dist/style.css +41 -0
  7. package/package.json +2 -2
  8. package/src/core/components.js +15 -14
  9. package/src/core/components2.js +37 -36
  10. package/src/core/components3.js +29 -7
  11. package/src/core/components4.js +23 -22
  12. package/src/core/components6.js +8 -7
  13. package/src/core/components7.js +10 -9
  14. package/src/core/index.js +1 -1
  15. package/src/core/pages.js +1 -0
  16. package/src/i18n/components/ActionCard.js +5 -0
  17. package/src/i18n/components/Actionsheet.js +5 -0
  18. package/src/i18n/components/Alert.js +5 -0
  19. package/src/i18n/components/Breadcrumbs.js +5 -0
  20. package/src/i18n/components/Calendar.js +5 -0
  21. package/src/i18n/components/CallCard.js +5 -0
  22. package/src/i18n/components/CallRow.js +5 -0
  23. package/src/i18n/components/Carousel.js +5 -0
  24. package/src/i18n/components/ChartCard.js +5 -0
  25. package/src/i18n/components/ChatAi.js +5 -0
  26. package/src/i18n/components/Chip.js +5 -0
  27. package/src/i18n/components/ChipInput.js +5 -0
  28. package/src/i18n/components/CodeInput.js +5 -0
  29. package/src/i18n/components/Combobox.js +5 -0
  30. package/src/i18n/components/CommandPalette.js +5 -0
  31. package/src/i18n/components/ConfirmDialog.js +5 -0
  32. package/src/i18n/components/ContactPanel.js +5 -0
  33. package/src/i18n/components/CopyButton.js +2 -0
  34. package/src/i18n/components/DataGroup.js +5 -0
  35. package/src/i18n/components/DataState.js +5 -0
  36. package/src/i18n/components/DataTable.js +5 -0
  37. package/src/i18n/components/DatePicker.js +5 -0
  38. package/src/i18n/components/DealCard.js +5 -0
  39. package/src/i18n/components/Drawer.js +5 -0
  40. package/src/i18n/components/ErrorPage.js +5 -0
  41. package/src/i18n/components/FileUpload.js +5 -0
  42. package/src/i18n/components/FullscreenDialog.js +5 -0
  43. package/src/i18n/components/Gallery.js +5 -0
  44. package/src/i18n/components/GuestCard.js +5 -0
  45. package/src/i18n/components/ImageUpload.js +5 -0
  46. package/src/i18n/components/ImageViewer.js +5 -0
  47. package/src/i18n/components/IncomingCall.js +5 -0
  48. package/src/i18n/components/InlineEdit.js +5 -0
  49. package/src/i18n/components/IntegrationCard.js +5 -0
  50. package/src/i18n/components/LoginForm.js +5 -0
  51. package/src/i18n/components/Map.js +5 -0
  52. package/src/i18n/components/Modal.js +5 -0
  53. package/src/i18n/components/MultiSelect.js +5 -0
  54. package/src/i18n/components/NotificationBell.js +5 -0
  55. package/src/i18n/components/NumberInput.js +5 -0
  56. package/src/i18n/components/Pagination.js +5 -0
  57. package/src/i18n/components/PasswordInput.js +5 -0
  58. package/src/i18n/components/Popconfirm.js +5 -0
  59. package/src/i18n/components/PricingCard.js +5 -0
  60. package/src/i18n/components/RamadanTracker.js +5 -0
  61. package/src/i18n/components/RangeCalendar.js +5 -0
  62. package/src/i18n/components/RangeSlider.js +5 -0
  63. package/src/i18n/components/Rating.js +5 -0
  64. package/src/i18n/components/RichEditor.js +5 -0
  65. package/src/i18n/components/Screensaver.js +5 -0
  66. package/src/i18n/components/SearchInput.js +5 -0
  67. package/src/i18n/components/SideNav.js +5 -0
  68. package/src/i18n/components/Snackbar.js +5 -0
  69. package/src/i18n/components/Sortable.js +5 -0
  70. package/src/i18n/components/Spinner.js +5 -0
  71. package/src/i18n/components/StatusPage.js +5 -0
  72. package/src/i18n/components/StepDialog.js +5 -0
  73. package/src/i18n/components/StepForm.js +5 -0
  74. package/src/i18n/components/TabTiles.js +5 -0
  75. package/src/i18n/components/Tag.js +5 -0
  76. package/src/i18n/components/TopNav.js +5 -0
  77. package/src/i18n/components/Tour.js +5 -0
  78. package/src/i18n/components/TourCard.js +5 -0
  79. package/src/i18n/components/TourPopover.js +5 -0
  80. package/src/i18n/components/TreeSelect.js +5 -0
  81. package/src/i18n/components/Validation.js +5 -0
  82. package/src/i18n/components/index.js +130 -0
  83. package/src/i18n/index.js +8 -6
  84. package/src/meta/domain.js +20 -0
  85. package/src/meta/groups.js +1 -1
  86. package/src/meta/pages.js +9 -1
  87. package/src/meta/templates.json +1 -1
  88. package/src/react/index.js +1 -0
  89. package/src/styles/components8.css +41 -0
  90. package/src/vue/index.js +1 -1
  91. package/types/i18n.d.ts +4 -2
  92. package/types/react.d.ts +80 -2
  93. package/types/vue-global.d.ts +1 -0
  94. package/types/vue.d.ts +83 -2
@@ -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: 'Search', onInput: e => set({ q: e.target.value }) })), ...(p.nodes || []).map(n => node(n, 0))) : null)); } },
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': 'Move up', 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': 'Move down', disabled: i === items.length - 1, onClick: () => drop(i + 1, i) }, icon(h, 'chevron-down', 14)))))); } },
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', 'Zoom in', 'plus'), zb(-1, 'zoomOut', 'Zoom out', 'minus')),
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 || 'Upload')), h('span', { class: 'zg-imgup__o' }, icon(h, 'camera', 18)),
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
  };
@@ -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 || 'Cancel')) },
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 || 'Image viewer', onClick: p.onClose },
30
- h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--ghost zg-iv__x', 'aria-label': 'Close', onClick: p.onClose }, icon(h, 'x', 20)),
31
- im.length > 1 ? h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--ghost zg-iv__p', 'aria-label': 'Previous', onClick: e => { e.stopPropagation(); go(-1); } }, icon(h, 'chevron-left', 22)) : null,
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': 'Next', onClick: e => { e.stopPropagation(); go(1); } }, icon(h, 'chevron-right', 22)) : null,
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 || 'Assistant' },
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': 'Typing' }, h('i'), h('i'), h('i')) : null),
40
- h('div', { class: 'zg-chat__f' }, h('input', { class: 'zg-chat__in', value: state.q, placeholder: p.placeholder || 'Ask anything…', 'aria-label': 'Message', onInput: e => set({ q: e.target.value }), onKeydown: e => { if (e.key === 'Enter') { e.preventDefault(); send(); } } }),
41
- h('button', { type: 'button', class: 'zg-ibtn zg-ibtn--brand', 'aria-label': 'Send', disabled: p.loading || !state.q.trim(), onClick: send }, icon(h, 'send', 18)))); } },
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: { cancel: 'Cancel' },
3
+ ar: { cancel: 'إلغاء' },
4
+ ru: { cancel: 'Отмена' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { close: 'Close' },
3
+ ar: { close: 'إغلاق' },
4
+ ru: { close: 'Закрыть' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { label: 'Breadcrumb' },
3
+ ar: { label: 'مسار التنقل' },
4
+ ru: { label: 'Хлебные крошки' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { prev: 'Previous month', next: 'Next month' },
3
+ ar: { prev: 'الشهر السابق', next: 'الشهر التالي' },
4
+ ru: { prev: 'Предыдущий месяц', next: 'Следующий месяц' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { play: 'Play' },
3
+ ar: { play: 'تشغيل' },
4
+ ru: { play: 'Воспроизвести' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { play: 'Play' },
3
+ ar: { play: 'تشغيل' },
4
+ ru: { play: 'Воспроизвести' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { prev: 'Previous', next: 'Next', slide: 'Slide' },
3
+ ar: { prev: 'السابق', next: 'التالي', slide: 'شريحة' },
4
+ ru: { prev: 'Предыдущий', next: 'Следующий', slide: 'Слайд' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { more: 'More' },
3
+ ar: { more: 'المزيد' },
4
+ ru: { more: 'Ещё' },
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: { remove: 'Remove' },
3
+ ar: { remove: 'إزالة' },
4
+ ru: { remove: 'Удалить' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { remove: 'Remove {name}' },
3
+ ar: { remove: 'إزالة {name}' },
4
+ ru: { remove: 'Удалить {name}' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { label: 'Code' },
3
+ ar: { label: 'الرمز' },
4
+ ru: { label: 'Код' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { placeholder: 'Search…', clear: 'Clear' },
3
+ ar: { placeholder: 'ابحث…', clear: 'مسح' },
4
+ ru: { placeholder: 'Поиск…', clear: 'Очистить' },
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: { cancel: 'Cancel', confirm: 'Confirm' },
3
+ ar: { cancel: 'إلغاء', confirm: 'تأكيد' },
4
+ ru: { cancel: 'Отмена', confirm: 'Подтвердить' },
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
+ };
@@ -1,3 +1,5 @@
1
1
  export default {
2
2
  en: { copy: 'Copy', copied: 'Copied!', failed: 'Copy failed' },
3
+ ar: { copy: 'نسخ', copied: 'تم النسخ!', failed: 'فشل النسخ' },
4
+ ru: { copy: 'Копировать', copied: 'Скопировано!', failed: 'Не удалось скопировать' },
3
5
  };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { expand: 'Expand' },
3
+ ar: { expand: 'توسيع' },
4
+ ru: { expand: 'Развернуть' },
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: { selectAll: 'Select all', selectRow: 'Select row' },
3
+ ar: { selectAll: 'تحديد الكل', selectRow: 'تحديد الصف' },
4
+ ru: { selectAll: 'Выбрать все', selectRow: 'Выбрать строку' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { placeholder: 'Select date', clear: 'Clear' },
3
+ ar: { placeholder: 'اختر التاريخ', clear: 'مسح' },
4
+ ru: { placeholder: 'Выберите дату', clear: 'Очистить' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { probability: 'Probability' },
3
+ ar: { probability: 'الاحتمال' },
4
+ ru: { probability: 'Вероятность' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { close: 'Close' },
3
+ ar: { close: 'إغلاق' },
4
+ ru: { close: 'Закрыть' },
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: { title: 'Drop files here or browse', hint: 'PDF, JPG up to 10 MB' },
3
+ ar: { title: 'أفلت الملفات هنا أو تصفح', hint: 'PDF وJPG حتى 10 ميغابايت' },
4
+ ru: { title: 'Перетащите файлы сюда или выберите', hint: 'PDF, JPG до 10 МБ' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { close: 'Close', save: 'Save' },
3
+ ar: { close: 'إغلاق', save: 'حفظ' },
4
+ ru: { close: 'Закрыть', save: 'Сохранить' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { photo: 'Photo' },
3
+ ar: { photo: 'صورة' },
4
+ ru: { photo: 'Фото' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { nights: '{n} nights' },
3
+ ar: { nights: '{n} ليالٍ' },
4
+ ru: { nights: '{n} ноч.' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { upload: 'Upload' },
3
+ ar: { upload: 'رفع' },
4
+ ru: { upload: 'Загрузить' },
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: { incoming: 'Incoming call', decline: 'Decline', answer: 'Answer' },
3
+ ar: { incoming: 'مكالمة واردة', decline: 'رفض', answer: 'رد' },
4
+ ru: { incoming: 'Входящий звонок', decline: 'Отклонить', answer: 'Ответить' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { save: 'Save', edit: 'Click to edit' },
3
+ ar: { save: 'حفظ', edit: 'انقر للتعديل' },
4
+ ru: { save: 'Сохранить', edit: 'Нажмите, чтобы изменить' },
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: 'Map', zoomIn: 'Zoom in', zoomOut: 'Zoom out' },
3
+ ar: { label: 'خريطة', zoomIn: 'تكبير', zoomOut: 'تصغير' },
4
+ ru: { label: 'Карта', zoomIn: 'Увеличить', zoomOut: 'Уменьшить' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { close: 'Close' },
3
+ ar: { close: 'إغلاق' },
4
+ ru: { close: 'Закрыть' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { selected: '{n} selected' },
3
+ ar: { selected: '{n} محدد' },
4
+ ru: { selected: 'Выбрано: {n}' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { label: 'Notifications', markAllRead: 'Mark all read' },
3
+ ar: { label: 'الإشعارات', markAllRead: 'تحديد الكل كمقروء' },
4
+ ru: { label: 'Уведомления', markAllRead: 'Отметить все как прочитанные' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { decrease: 'Decrease', increase: 'Increase' },
3
+ ar: { decrease: 'تقليل', increase: 'زيادة' },
4
+ ru: { decrease: 'Уменьшить', increase: 'Увеличить' },
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: { show: 'Show password', hide: 'Hide password' },
3
+ ar: { show: 'إظهار كلمة المرور', hide: 'إخفاء كلمة المرور' },
4
+ ru: { show: 'Показать пароль', hide: 'Скрыть пароль' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { no: 'No', yes: 'Yes' },
3
+ ar: { no: 'لا', yes: 'نعم' },
4
+ ru: { no: 'Нет', yes: 'Да' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { choose: 'Choose' },
3
+ ar: { choose: 'اختيار' },
4
+ ru: { choose: 'Выбрать' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { day: 'Day {day} of 30', label: 'Ramadan tracker' },
3
+ ar: { day: 'اليوم {day} من 30', label: 'متتبع رمضان' },
4
+ ru: { day: 'День {day} из 30', label: 'Трекер Рамадана' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { prev: 'Previous', next: 'Next' },
3
+ ar: { prev: 'السابق', next: 'التالي' },
4
+ ru: { prev: 'Назад', next: 'Далее' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { min: 'Min', max: 'Max' },
3
+ ar: { min: 'الحد الأدنى', max: 'الحد الأقصى' },
4
+ ru: { min: 'Мин.', max: 'Макс.' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { label: 'Rating', stars: '{n} stars' },
3
+ ar: { label: 'التقييم', stars: '{n} نجوم' },
4
+ ru: { label: 'Рейтинг', stars: 'Звёзд: {n}' },
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: { label: 'Screensaver' },
3
+ ar: { label: 'شاشة التوقف' },
4
+ ru: { label: 'Заставка' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { placeholder: 'Search', clear: 'Clear' },
3
+ ar: { placeholder: 'بحث', clear: 'مسح' },
4
+ ru: { placeholder: 'Поиск', clear: 'Очистить' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { toggle: 'Toggle sidebar', collapse: 'Collapse' },
3
+ ar: { toggle: 'تبديل الشريط الجانبي', collapse: 'طي' },
4
+ ru: { toggle: 'Переключить боковую панель', collapse: 'Свернуть' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { close: 'Close' },
3
+ ar: { close: 'إغلاق' },
4
+ ru: { close: 'Закрыть' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { moveUp: 'Move up', moveDown: 'Move down' },
3
+ ar: { moveUp: 'نقل لأعلى', moveDown: 'نقل لأسفل' },
4
+ ru: { moveUp: 'Переместить вверх', moveDown: 'Переместить вниз' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { loading: 'Loading' },
3
+ ar: { loading: 'جارٍ التحميل' },
4
+ ru: { loading: 'Загрузка' },
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
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { close: 'Close', previous: 'Previous', next: 'Next', submit: 'Submit' },
3
+ ar: { close: 'إغلاق', previous: 'السابق', next: 'التالي', submit: 'إرسال' },
4
+ ru: { close: 'Закрыть', previous: 'Назад', next: 'Далее', submit: 'Отправить' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { back: 'Back', next: 'Next', finish: 'Finish' },
3
+ ar: { back: 'رجوع', next: 'التالي', finish: 'إنهاء' },
4
+ ru: { back: 'Назад', next: 'Следующий', finish: 'Готово' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { add: 'Add' },
3
+ ar: { add: 'إضافة' },
4
+ ru: { add: 'Добавить' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { remove: 'Remove' },
3
+ ar: { remove: 'إزالة' },
4
+ ru: { remove: 'Удалить' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { label: 'Main' },
3
+ ar: { label: 'الرئيسية' },
4
+ ru: { label: 'Основная' },
5
+ };
@@ -0,0 +1,5 @@
1
+ export default {
2
+ en: { label: 'Tour' },
3
+ ar: { label: 'جولة تعريفية' },
4
+ ru: { label: 'Тур' },
5
+ };