anentrypoint-design 0.0.304 → 0.0.306

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.304",
3
+ "version": "0.0.306",
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",
@@ -223,6 +223,45 @@ export function useMediaQuery(query) {
223
223
  };
224
224
  }
225
225
 
226
+ // ---------------------------------------------------------------------------
227
+ // Grid / GridItem — 24-column responsive layout primitive (screen-real-estate
228
+ // density: dense multi-column panels without a hand-rolled grid-template-
229
+ // columns per consumer). Column-span props are integers 1-24 (or `true` for
230
+ // full-width/auto-grow, or `0` to hide at that breakpoint) evaluated at four
231
+ // tiers mirroring BP_SM/MD/LG/XL (480/768/1024/1440) via media queries in
232
+ // editor-primitives.css — no JS-side matchMedia needed, CSS custom
233
+ // properties + @media do the layout work so it degrades gracefully with
234
+ // SSR/no-hydration. Grid itself is a flex row wrapper; GridItem computes
235
+ // flex-basis/max-width from its span at each tier.
236
+ // ---------------------------------------------------------------------------
237
+ export function Grid({ gap, justify, align, children, key } = {}) {
238
+ const style = [
239
+ gap != null ? `gap:${typeof gap === 'number' ? gap + 'px' : gap}` : '',
240
+ justify ? `justify-content:${justify}` : '',
241
+ align ? `align-items:${align}` : '',
242
+ ].filter(Boolean).join(';');
243
+ return h('div', { key, class: 'ds-ep-grid', style: style || null }, children);
244
+ }
245
+
246
+ function gridSpanStyle(prefix, val) {
247
+ if (val === undefined) return '';
248
+ if (val === true) return `--${prefix}-basis:100%;--${prefix}-grow:1;--${prefix}-display:inherit;`;
249
+ if (val === 0) return `--${prefix}-display:none;`;
250
+ const pct = Math.max(0, Math.min(100, (100 / 24) * val));
251
+ return `--${prefix}-basis:${pct}%;--${prefix}-grow:0;--${prefix}-display:inherit;`;
252
+ }
253
+
254
+ export function GridItem({ xs, sm, md, lg, xl, children, key } = {}) {
255
+ const style = [
256
+ gridSpanStyle('xs', xs),
257
+ gridSpanStyle('sm', sm),
258
+ gridSpanStyle('md', md),
259
+ gridSpanStyle('lg', lg),
260
+ gridSpanStyle('xl', xl),
261
+ ].join('');
262
+ return h('div', { key, class: 'ds-ep-grid-item', style: style || null }, children);
263
+ }
264
+
226
265
  // ---------------------------------------------------------------------------
227
266
  // FocusTrap — wraps subtree, traps Tab/Shift+Tab. Mount/unmount lifecycle is
228
267
  // managed via DOM-level keydown listener attached when first focused.
@@ -592,25 +631,69 @@ export function toast({ message, kind = 'info', duration = 3000 } = {}) {
592
631
  // gm-pager. page is 1-indexed; pageCount<=1 disables both buttons (no
593
632
  // divide-by-zero, no dead-end enabled control). total (optional) renders an
594
633
  // item-count suffix ("42 items") alongside the page label.
634
+ //
635
+ // numbered=true switches to a compact numbered-button row (screen-real-estate
636
+ // dense mode) instead of the prev/next label: always shows first, last, the
637
+ // current page, and up to `siblingCount` neighbors either side, collapsing
638
+ // gaps into an ellipsis span. Falls back to prev/next automatically when
639
+ // pageCount<=1. The prev/next contract (default) is untouched.
595
640
  // ---------------------------------------------------------------------------
596
- export function Pager({ page = 1, pageCount = 1, onPage, total, itemLabel = 'items' } = {}) {
641
+ function buildPageRange(count, page, siblingCount) {
642
+ const limit = siblingCount * 2 + 3; // first + last + current + siblings
643
+ if (count <= limit) return Array.from({ length: count }, (_, i) => i + 1);
644
+ const pages = new Set([1, count, page]);
645
+ for (let i = 1; i <= siblingCount; i++) {
646
+ pages.add(page - i);
647
+ pages.add(page + i);
648
+ }
649
+ const sorted = [...pages].filter((p) => p >= 1 && p <= count).sort((a, b) => a - b);
650
+ const result = [];
651
+ let prev = null;
652
+ for (const p of sorted) {
653
+ if (prev !== null && p - prev > 1) result.push('...');
654
+ result.push(p);
655
+ prev = p;
656
+ }
657
+ return result;
658
+ }
659
+
660
+ export function Pager({ page = 1, pageCount = 1, onPage, total, itemLabel = 'items', numbered = false, siblingCount = 1 } = {}) {
597
661
  const safeCount = Math.max(1, pageCount || 1);
598
662
  const safePage = Math.min(Math.max(1, page || 1), safeCount);
599
663
  const atStart = safePage <= 1;
600
664
  const atEnd = safePage >= safeCount;
665
+ const prevBtn = h('button', {
666
+ type: 'button', class: 'ds-ep-pager-btn', disabled: atStart ? 'disabled' : null,
667
+ 'aria-label': 'previous page',
668
+ onclick: () => { if (!atStart && onPage) onPage(safePage - 1); },
669
+ }, '<-');
670
+ const nextBtn = h('button', {
671
+ type: 'button', class: 'ds-ep-pager-btn', disabled: atEnd ? 'disabled' : null,
672
+ 'aria-label': 'next page',
673
+ onclick: () => { if (!atEnd && onPage) onPage(safePage + 1); },
674
+ }, '->');
675
+ if (numbered) {
676
+ const range = buildPageRange(safeCount, safePage, Math.max(1, siblingCount || 1));
677
+ return h('div', { class: 'ds-ep-pager ds-ep-pager-numbered', role: 'group', 'aria-label': 'pagination' },
678
+ prevBtn,
679
+ ...range.map((p, i) => p === '...'
680
+ ? h('span', { key: 'ellipsis-' + i, class: 'ds-ep-pager-ellipsis' }, '...')
681
+ : h('button', {
682
+ key: 'p' + p, type: 'button',
683
+ class: 'ds-ep-pager-num' + (p === safePage ? ' is-current' : ''),
684
+ 'aria-current': p === safePage ? 'page' : null,
685
+ 'aria-label': 'page ' + p,
686
+ onclick: () => { if (p !== safePage && onPage) onPage(p); },
687
+ }, String(p))),
688
+ nextBtn,
689
+ total != null ? h('span', { class: 'ds-ep-pager-total' }, total + ' ' + itemLabel) : null
690
+ );
691
+ }
601
692
  return h('div', { class: 'ds-ep-pager', role: 'group', 'aria-label': 'pagination' },
602
- h('button', {
603
- type: 'button', class: 'ds-ep-pager-btn', disabled: atStart ? 'disabled' : null,
604
- 'aria-label': 'previous page',
605
- onclick: () => { if (!atStart && onPage) onPage(safePage - 1); },
606
- }, '<-'),
693
+ prevBtn,
607
694
  h('span', { class: 'ds-ep-pager-label' },
608
695
  'page ' + safePage + ' / ' + safeCount + (total != null ? ' (' + total + ' ' + itemLabel + ')' : '')),
609
- h('button', {
610
- type: 'button', class: 'ds-ep-pager-btn', disabled: atEnd ? 'disabled' : null,
611
- 'aria-label': 'next page',
612
- onclick: () => { if (!atEnd && onPage) onPage(safePage + 1); },
613
- }, '->')
696
+ nextBtn
614
697
  );
615
698
  }
616
699
 
@@ -747,3 +830,53 @@ export function IconButtonGroup({ items = [], value, onChange, dense = false } =
747
830
  }, it.glyph != null ? it.glyph : it.label))
748
831
  );
749
832
  }
833
+
834
+ // ---------------------------------------------------------------------------
835
+ // Collapse — progressive-disclosure toggle panel (screen-real-estate
836
+ // density: property inspectors, nested settings, FAQ-style panels).
837
+ // Controlled component: caller owns `expanded` state and passes `onToggle`,
838
+ // same pattern as Drawer/Dialog `open`/`onClose` above — no internal state.
839
+ // ---------------------------------------------------------------------------
840
+ export function Collapse({ title, expanded = false, onToggle, children, key } = {}) {
841
+ return h('div', { key, class: 'ds-ep-collapse' + (expanded ? ' is-expanded' : '') },
842
+ h('button', {
843
+ type: 'button', class: 'ds-ep-collapse-head',
844
+ 'aria-expanded': expanded ? 'true' : 'false',
845
+ onclick: () => { if (onToggle) onToggle(!expanded); },
846
+ },
847
+ h('span', { class: 'ds-ep-collapse-chevron' }, expanded ? 'v' : '>'),
848
+ h('span', { class: 'ds-ep-collapse-title' }, title)),
849
+ expanded ? h('div', { class: 'ds-ep-collapse-body' }, children) : null);
850
+ }
851
+
852
+ // ---------------------------------------------------------------------------
853
+ // CollapseGroup — accordion wrapper enforcing single-open-at-a-time when
854
+ // `accordion=true` (default false — group just lays out children, each
855
+ // Collapse still individually controlled). `openId`/`onOpenChange` drive the
856
+ // accordion; `items` is [{id, title, children}].
857
+ // ---------------------------------------------------------------------------
858
+ export function CollapseGroup({ items = [], openId, onOpenChange, accordion = false, key } = {}) {
859
+ return h('div', { key, class: 'ds-ep-collapse-group' },
860
+ ...items.map((it) => Collapse({
861
+ key: it.id,
862
+ title: it.title,
863
+ expanded: accordion ? it.id === openId : Boolean(it.expanded),
864
+ onToggle: (next) => {
865
+ if (!onOpenChange) return;
866
+ if (accordion) onOpenChange(next ? it.id : null);
867
+ else onOpenChange(it.id, next);
868
+ },
869
+ children: it.children,
870
+ })));
871
+ }
872
+
873
+ // ---------------------------------------------------------------------------
874
+ // Divider — plain rule, optional centered text label, optional vertical
875
+ // orientation (for segmenting dense panels without a full Section wrapper).
876
+ // ---------------------------------------------------------------------------
877
+ export function Divider({ label, vertical = false, key } = {}) {
878
+ if (vertical) return h('span', { key, class: 'ds-ep-divider ds-ep-divider-vertical', role: 'separator', 'aria-orientation': 'vertical' });
879
+ if (!label) return h('hr', { key, class: 'ds-ep-divider' });
880
+ return h('div', { key, class: 'ds-ep-divider ds-ep-divider-labeled', role: 'separator' },
881
+ h('span', { class: 'ds-ep-divider-label' }, label));
882
+ }
package/src/components.js CHANGED
@@ -80,6 +80,9 @@ export {
80
80
  Drawer, Dialog, FocusTrap,
81
81
  Toast, toast,
82
82
  Pager, JsonViewer,
83
+ Grid, GridItem,
84
+ Collapse, CollapseGroup,
85
+ Divider,
83
86
  useMediaQuery,
84
87
  BP_SM, BP_MD, BP_LG, BP_XL
85
88
  } from './components/editor-primitives.js';
Binary file