@c2n/dashboard 0.0.14 → 0.0.16

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.
@@ -1 +1 @@
1
- {"schemaVersion":"1.0.0","readme":"","modules":[{"kind":"javascript-module","path":"src/dashboard.ts","declarations":[{"kind":"class","description":"Grid of resizable panes. The children are `c2-dash-card` elements, placed by their `col`/`row` attributes; each\none draws drag handles on the edges it shares with a neighbour, and dragging one resizes the whole track, so the\ncards on either side stay aligned. `columns` and `rows` take a track count (`columns=\"3\"` is three equal columns)\nor an explicit track list (`columns=\"320px 1fr\"`); a track is switched to pixels the first time it is dragged, and\nthe `fr` tracks around it give up the space in proportion to their weight, down to the minimums. With a\n`storage-key` the sizes survive a reload.\n\n`layouts` makes the grid responsive without a remount: each entry names a media query and the tracks and card\nplacements to use while it matches, the first match wins, and every entry keeps its own stored sizes under\n`<storage-key>@<media>`.\n\nPlacement is the application's: the grid never re-places cards on its own. A pane removed or hidden at runtime\nleaves its cells empty and its neighbours where they were, and a pane added at runtime lands exactly where its\n`col`/`row` say, on top of whatever is already there if that cell is taken. To close a gap, or to make room, set\nthe cards' `col`/`row`/`col-span`/`row-span` or hand the grid a `layout` record — both are applied in place.\n\nThe grid is the sizing authority: a card never sets its own width. Give the element a height (or place it in a\nflex/grid parent that does) whenever the rows use `fr`, since the row tracks divide the host's height.","name":"Dashboard","cssProperties":[{"type":{"text":"pixel"},"description":"Gutter between the cards. The whole gutter drags: each card's handle is centred on its edge and as thick as the gap (never under `--c2-dash-card__handle--size`).","name":"--c2-dashboard--gap","default":"8px"},{"type":{"text":"padding"},"description":"Inset around the tracks. With a `background` it is what turns the gutters into a visible frame between the panes.","name":"--c2-dashboard--padding","default":"0px"},{"type":{"text":"background"},"name":"--c2-dashboard--background","default":"transparent"},{"type":{"text":"border"},"name":"--c2-dashboard--border","default":"none"},{"type":{"text":"border-radius"},"name":"--c2-dashboard--border-radius","default":"0px"}],"slots":[{"description":"The `c2-dash-card` panes. Anything else becomes an ordinary grid item, placed by your own CSS.","name":""}],"members":[{"kind":"field","name":"columns","type":{"text":"number | string | string[]"},"default":"2","description":"Column count (`3`) or an explicit track list (`'320px 1fr'`). Each entry must be one simple size.","attribute":"columns"},{"kind":"field","name":"rows","type":{"text":"number | string | string[]"},"default":"1","description":"Row count (`2`) or an explicit track list (`'auto 1fr'`).","attribute":"rows"},{"kind":"field","name":"minColumnWidth","type":{"text":"number"},"default":"50","description":"Floor for every column, in pixels. A card's own `min-width` raises it for the tracks that card covers.","attribute":"min-column-width"},{"kind":"field","name":"minRowHeight","type":{"text":"number"},"default":"50","description":"Floor for every row, in pixels. A card's own `min-height` raises it for the tracks that card covers.","attribute":"min-row-height"},{"kind":"field","name":"storageKey","type":{"text":"string | undefined"},"default":"undefined","description":"`localStorage` key the track sizes are stored under. Without it the grid starts from the authored tracks.","attribute":"storage-key"},{"kind":"field","name":"layout","type":{"text":"Record<string, DashCardPlacement> | undefined"},"default":"undefined","description":"Placement overrides keyed by the cards' `card-id`, for a layout that is chosen at runtime rather than authored\nin the markup. Each entry wins over the card's own `col`/`row`/`col-span`/`row-span`/visibility. This is also\nhow an app re-flows the remaining panes after one was removed: the grid does not do that by itself."},{"kind":"field","name":"layouts","type":{"text":"DashboardResponsiveLayout[] | undefined"},"default":"undefined","description":"Responsive variants, in priority order: the first entry whose `media` matches supplies the tracks and the card\nplacements, and the grid switches as the viewport crosses a breakpoint. Nothing is stored across entries — each\none keeps its own sizes under `<storage-key>@<media>`."},{"kind":"field","name":"columnTracks","type":{"text":"string[]"},"privacy":"private","default":"[]"},{"kind":"field","name":"rowTracks","type":{"text":"string[]"},"privacy":"private","default":"[]"},{"kind":"field","name":"activeLayout","type":{"text":"number"},"privacy":"private","default":"-1","description":"Index into `layouts` of the entry in force, `-1` for the authored grid."},{"kind":"field","name":"cards","privacy":"private","default":"new Set<DashboardCard>()"},{"kind":"field","name":"mediaQueries","type":{"text":"MediaQueryList[]"},"privacy":"private","default":"[]"},{"kind":"field","name":"handleMediaChange","privacy":"private","readonly":true},{"kind":"field","name":"pixelCache","privacy":"private","default":"new Map<'column' | 'row', number[]>()","description":"Used track sizes, valid until the next write to the tracks."},{"kind":"field","name":"columnSizes","type":{"text":"string[]"},"description":"Column tracks as they are laid out right now.","readonly":true},{"kind":"field","name":"rowSizes","type":{"text":"string[]"},"description":"Row tracks as they are laid out right now.","readonly":true},{"kind":"field","name":"columnCount","type":{"text":"number"},"readonly":true},{"kind":"field","name":"rowCount","type":{"text":"number"},"readonly":true},{"kind":"field","name":"activeResponsiveLayout","type":{"text":"DashboardResponsiveLayout | undefined"},"description":"The entry of `layouts` in force, or `undefined` while the authored grid is.","readonly":true},{"kind":"method","name":"reset","description":"Back to the authored tracks of the layout in force, and its stored ones are forgotten."},{"kind":"method","name":"registerCard","parameters":[{"name":"card","type":{"text":"DashboardCard"}}]},{"kind":"method","name":"unregisterCard","parameters":[{"name":"card","type":{"text":"DashboardCard"}}]},{"kind":"method","name":"placementOf","return":{"type":{"text":"DashCardPlacement | undefined"}},"parameters":[{"name":"cardId","type":{"text":"string | undefined"}}]},{"kind":"method","name":"resizeColumn","return":{"type":{"text":"number"}},"parameters":[{"name":"index","type":{"text":"number"}},{"name":"delta","type":{"text":"number"}}]},{"kind":"method","name":"resizeRow","return":{"type":{"text":"number"}},"parameters":[{"name":"index","type":{"text":"number"}},{"name":"delta","type":{"text":"number"}}]},{"kind":"method","name":"commitResize"},{"kind":"method","name":"splitterValue","return":{"type":{"text":"number"}},"parameters":[{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"index","type":{"text":"number"}}],"description":"Where the splitter after `index` sits, as a percentage of the tracks' total. A focusable `separator` is a\nwindow splitter, and a window splitter has to report a value."},{"kind":"method","name":"trackPixels","privacy":"private","return":{"type":{"text":"number[]"}},"parameters":[{"name":"axis","type":{"text":"'column' | 'row'"}}],"description":"Reading a used track size forces layout, and a drag asks for it from every card's handles on every pointer\nmove. The answer cannot change until something writes to the DOM, so it is cached until one of them does."},{"kind":"method","name":"freeSpace","privacy":"private","return":{"type":{"text":"number"}},"parameters":[{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"tracks","type":{"text":"number[]"}}],"description":"What is left of the host along `axis` once the tracks, the gutters and the padding have taken their share."},{"kind":"method","name":"emitLayoutChange","privacy":"private"},{"kind":"method","name":"resizeTrack","privacy":"private","return":{"type":{"text":"{ tracks: string[]; applied: number } | undefined"}},"parameters":[{"name":"tracks","type":{"text":"string[]"}},{"name":"index","type":{"text":"number"}},{"name":"delta","type":{"text":"number"}},{"name":"axis","type":{"text":"'column' | 'row'"}}]},{"kind":"method","name":"trackMin","privacy":"private","return":{"type":{"text":"number"}},"parameters":[{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"index","type":{"text":"number"}}],"description":"The largest minimum any card covering this track asks for, spread over the tracks that card spans."},{"kind":"method","name":"watchMedia","privacy":"private","description":"One `MediaQueryList` per entry of `layouts`, listened to for as long as the element is connected. Whichever\nentry matches first is the one in force; the listeners re-run the choice whenever any of them flips."},{"kind":"method","name":"unwatchMedia","privacy":"private"},{"kind":"method","name":"resolveActiveLayout","privacy":"private","return":{"type":{"text":"number"}}},{"kind":"field","name":"activeStorageKey","type":{"text":"string | undefined"},"privacy":"private","description":"Each entry of `layouts` stores its own sizes: `<storage-key>@<media>`; the authored grid uses the bare key.","readonly":true},{"kind":"method","name":"syncTracks","privacy":"private"},{"kind":"method","name":"readStored","privacy":"private","return":{"type":{"text":"StoredLayout | null"}}},{"kind":"method","name":"persist","privacy":"private"}],"events":[{"name":"layout-change","type":{"text":"CustomEvent<DashboardLayoutChangeDetail>"},"description":"The track sizes changed: a gesture ended, `reset()` was called, or another entry of `layouts` took over. Does not bubble: listen on the element."}],"attributes":[{"name":"columns","type":{"text":"number | string | string[]"},"default":"2","description":"Column count (`3`) or an explicit track list (`'320px 1fr'`). Each entry must be one simple size.","fieldName":"columns"},{"name":"rows","type":{"text":"number | string | string[]"},"default":"1","description":"Row count (`2`) or an explicit track list (`'auto 1fr'`).","fieldName":"rows"},{"name":"min-column-width","type":{"text":"number"},"default":"50","description":"Floor for every column, in pixels. A card's own `min-width` raises it for the tracks that card covers.","fieldName":"minColumnWidth"},{"name":"min-row-height","type":{"text":"number"},"default":"50","description":"Floor for every row, in pixels. A card's own `min-height` raises it for the tracks that card covers.","fieldName":"minRowHeight"},{"name":"storage-key","type":{"text":"string | undefined"},"default":"undefined","description":"`localStorage` key the track sizes are stored under. Without it the grid starts from the authored tracks.","fieldName":"storageKey"}],"superclass":{"name":"LitElement","package":"lit"},"tagName":"c2-dashboard","customElement":true}],"exports":[{"kind":"js","name":"DashCardPlacement","declaration":{"name":"DashCardPlacement","module":"./dashboard-host"}},{"kind":"js","name":"Dashboard","declaration":{"name":"Dashboard","module":"src/dashboard.ts"}},{"kind":"custom-element-definition","name":"c2-dashboard","declaration":{"name":"Dashboard","module":"src/dashboard.ts"}}]},{"kind":"javascript-module","path":"src/dash-card.ts","declarations":[{"kind":"class","description":"One pane of a `c2-dashboard`. It owns its place in the grid (`col`, `row`, `col-span`, `row-span`), the drag\nhandles on the edges it shares with a neighbour, and the optional expand controls; it draws no surface of its\nown, so put a `c2-card` — or any markup — in the default slot.\n\nA handle resizes the whole grid track, never just this card, and it only appears where there is a neighbour to\ntake the space from: the right edge has one when another column follows, the left edge when one precedes. Drag\nit, or focus it and use the arrow keys (10px a step, 1px with Shift).\n\nFilling the `header`, `actions` or `footer` slot turns on that row; with the header and actions both empty the\nexpand controls float over the top-right corner of the pane instead. An expanded card covers its neighbours on\nan opaque `--c2-dash-card__expanded--background` (the theme's surface colour), while the card itself stays\ntransparent at rest.\n\nA card that arrives while the grid is already on screen fades and scales in; one that leaves — through the\ngrid's `layout` record (`visible: false`) or through `dismiss()`, which removes the element once the animation\nhas played — fades out the same way. Cards present at load do not animate, and `prefers-reduced-motion` turns\nboth off.\n\nEvery built-in icon is a slot whose fallback is the default drawing, so a pane can use the host application's own\nicon set without giving up the behaviour.","name":"DashCard","cssProperties":[{"type":{"text":"background"},"name":"--c2-dash-card--background","default":"transparent"},{"type":{"text":"border"},"name":"--c2-dash-card--border","default":"none"},{"type":{"text":"border-radius"},"name":"--c2-dash-card--border-radius","default":"0px"},{"type":{"text":"box-shadow"},"name":"--c2-dash-card--box-shadow","default":"none"},{"type":{"text":"padding"},"name":"--c2-dash-card--padding","default":"0px"},{"type":{"text":"overflow"},"description":"`hidden` keeps the content inside the track; switch it to `visible` for a pane that has to overflow, such as one holding a menu.","name":"--c2-dash-card--overflow","default":"hidden"},{"type":{"text":"background"},"description":"Fill while the card is expanded over its neighbours, so they do not show through; the card's own `background` stays transparent.","name":"--c2-dash-card__expanded--background","default":"#ffffff"},{"type":{"text":"number"},"name":"--c2-dash-card__expanded--z-index","default":"20"},{"type":{"text":"duration"},"description":"Fade and scale-in of a card added to a grid that is already on screen, or shown again through the layout record. `0ms` disables it.","name":"--c2-dash-card__enter--animation-duration","default":"200ms"},{"type":{"text":"duration"},"description":"Fade-out before a card is hidden by the layout record or removed by `dismiss()`. `0ms` disables it.","name":"--c2-dash-card__leave--animation-duration","default":"160ms"},{"type":{"text":"duration"},"description":"Length of the scale-in the card plays when it expands or collapses. Ignored under `prefers-reduced-motion`.","name":"--c2-dash-card__expanded--animation-duration","default":"200ms"},{"type":{"text":"pixel"},"name":"--c2-dash-card__header--min-height","default":"44px"},{"type":{"text":"padding"},"name":"--c2-dash-card__header--padding-block","default":"8px"},{"type":{"text":"padding"},"name":"--c2-dash-card__header--padding-inline","default":"12px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__header--gap","default":"12px"},{"type":{"text":"background"},"name":"--c2-dash-card__header--background","default":"transparent"},{"type":{"text":"border"},"name":"--c2-dash-card__header--border-bottom","default":"none"},{"type":{"text":"color"},"name":"--c2-dash-card__header--color","default":"#18181b"},{"type":{"text":"pixel"},"name":"--c2-dash-card__header--font-size","default":"14px"},{"type":{"text":"font-weight"},"name":"--c2-dash-card__header--font-weight","default":"600"},{"type":{"text":"pixel"},"name":"--c2-dash-card__footer--min-height","default":"36px"},{"type":{"text":"padding"},"name":"--c2-dash-card__footer--padding-block","default":"6px"},{"type":{"text":"padding"},"name":"--c2-dash-card__footer--padding-inline","default":"12px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__footer--gap","default":"8px"},{"type":{"text":"background"},"name":"--c2-dash-card__footer--background","default":"transparent"},{"type":{"text":"border"},"name":"--c2-dash-card__footer--border-top","default":"none"},{"type":{"text":"color"},"name":"--c2-dash-card__footer--color","default":"#71717a"},{"type":{"text":"pixel"},"name":"--c2-dash-card__footer--font-size","default":"12px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__actions--gap","default":"8px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__controls--gap","default":"2px"},{"type":{"text":"pixel"},"description":"Inset of the floating control group from the top-right corner, used only while the header row is off.","name":"--c2-dash-card__controls--offset","default":"4px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__control--size","default":"24px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__control--icon-size","default":"16px"},{"type":{"text":"border-radius"},"name":"--c2-dash-card__control--border-radius","default":"6px"},{"type":{"text":"color"},"name":"--c2-dash-card__control--color","default":"#71717a"},{"type":{"text":"background"},"name":"--c2-dash-card__control--background","default":"transparent"},{"type":{"text":"background"},"name":"--c2-dash-card__control__hover--background","default":"#f4f4f5"},{"type":{"text":"color"},"name":"--c2-dash-card__control__hover--color","default":"#18181b"},{"type":{"text":"outline"},"name":"--c2-dash-card__control__focus--outline","default":"2px solid rgba(2, 101, 220, 0.4)"},{"type":{"text":"pixel"},"name":"--c2-dash-card__control__focus--outline-offset","default":"2px"},{"type":{"text":"pixel"},"description":"Smallest thickness of the grab area on an edge. Inside a grid the handle is as thick as the gutter when that is wider, centred on the edge, so the whole gutter drags.","name":"--c2-dash-card__handle--size","default":"6px"},{"type":{"text":"pixel"},"description":"Gap between the handle's visible bar and the ends of the edge.","name":"--c2-dash-card__handle--inset","default":"2px"},{"type":{"text":"background"},"name":"--c2-dash-card__handle--background","default":"transparent"},{"type":{"text":"background"},"name":"--c2-dash-card__handle__hover--background","default":"rgba(2, 101, 220, 0.2)"},{"type":{"text":"background"},"name":"--c2-dash-card__handle__active--background","default":"rgb(2, 101, 220)"},{"type":{"text":"border-radius"},"name":"--c2-dash-card__handle--border-radius","default":"999px"},{"type":{"text":"duration"},"name":"--c2-dash-card__handle--transition-duration","default":"150ms"},{"type":{"text":"outline"},"name":"--c2-dash-card__handle__focus--outline","default":"2px solid rgba(2, 101, 220, 0.4)"}],"cssParts":[{"description":"Conditional row containing the `header` and `actions` slots, or the floating controls when both are empty.","name":"header"},{"description":"The wrapper around the default slot.","name":"body"},{"description":"Conditional row wrapping the assigned `footer` slot.","name":"footer"},{"description":"Component-owned group containing the `controls` slot and built-in expand-button fallbacks.","name":"controls"},{"description":"One built-in expand button.","name":"control"},{"description":"Every drag handle. Each also carries the part of its edge.","name":"handle"},{"description":"The handle on the left edge.","name":"handle-left"},{"description":"The handle on the right edge.","name":"handle-right"},{"description":"The handle on the top edge.","name":"handle-top"},{"description":"The handle on the bottom edge.","name":"handle-bottom"}],"slots":[{"description":"Pane content. It fills the pane: the body is a column flex box and every slotted child is a `flex: 1` item with `min-height: 0`, so a chart or an editor follows the row track without a `height: 100%` chain.","name":""},{"description":"Title area of the header row; filling it turns the row on.","name":"header"},{"description":"Your own controls at the end of the header row, before the built-in expand buttons and separated from them by `--c2-dash-card__actions--gap`.","name":"actions"},{"description":"Your own controls inside the built-in group, immediately before the expand buttons — for a button that belongs with them, such as a refresh or a close.","name":"controls"},{"description":"Status bar under the pane content; filling it turns the row on.","name":"footer"},{"description":"Icon of the full-width control while the card is not expanded that way.","name":"expand-width-icon"},{"description":"Icon of the full-width control while it is.","name":"collapse-width-icon"},{"description":"Icon of the full-height control while the card is not expanded that way.","name":"expand-height-icon"},{"description":"Icon of the full-height control while it is.","name":"collapse-height-icon"},{"description":"Icon of the fullscreen control while the card is not expanded.","name":"expand-full-icon"},{"description":"Icon of the fullscreen control while it is.","name":"collapse-full-icon"}],"members":[{"kind":"field","name":"cardId","type":{"text":"string | undefined"},"default":"undefined","description":"Identifier the grid's `layout` record is keyed by.","attribute":"card-id"},{"kind":"field","name":"col","type":{"text":"number"},"default":"1","description":"1-based column the card starts in.","attribute":"col"},{"kind":"field","name":"row","type":{"text":"number"},"default":"1","description":"1-based row the card starts in.","attribute":"row"},{"kind":"field","name":"colSpan","type":{"text":"number"},"default":"1","description":"Number of columns the card occupies.","attribute":"col-span"},{"kind":"field","name":"rowSpan","type":{"text":"number"},"default":"1","description":"Number of rows the card occupies.","attribute":"row-span"},{"kind":"field","name":"minWidth","type":{"text":"number"},"default":"0","description":"Smallest width in pixels the card accepts; it raises the minimum of every column it covers.","attribute":"min-width"},{"kind":"field","name":"minHeight","type":{"text":"number"},"default":"0","description":"Smallest height in pixels the card accepts; it raises the minimum of every row it covers.","attribute":"min-height"},{"kind":"field","name":"resize","type":{"text":"DashCardResize"},"default":"'both'","description":"Which edges carry a drag handle.","attribute":"resize","reflects":true},{"kind":"field","name":"expandWidth","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card across every column.","attribute":"expand-width"},{"kind":"field","name":"expandHeight","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card across every row.","attribute":"expand-height"},{"kind":"field","name":"expandFull","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card over the whole grid.","attribute":"expand-full"},{"kind":"field","name":"expanded","type":{"text":"DashCardExpanded"},"default":"'none'","description":"How far the card is currently expanded. Settable, so an app can expand a card from its own control.","attribute":"expanded","reflects":true},{"kind":"field","name":"slotPresence","privacy":"private","readonly":true,"default":"new SlotPresenceController(this, ['header', 'actions', 'controls', 'footer'])"},{"kind":"field","name":"dashboard","type":{"text":"DashboardHost | undefined"},"privacy":"private","default":"undefined"},{"kind":"field","name":"leaving","type":{"text":"boolean"},"privacy":"private","default":"false","description":"`true` while the leave animation plays: the handles are gone, the placement is kept until it ends."},{"kind":"field","name":"motion","type":{"text":"Animation | undefined"},"privacy":"private","description":"The enter or leave animation in flight — or the finished leave, kept so a return can cancel its fill."},{"kind":"field","name":"enterPending","type":{"text":"boolean"},"privacy":"private","default":"false","description":"Set when the card should animate in after its next render."},{"kind":"field","name":"constraint","type":{"text":"DashCardConstraint | undefined"},"description":"The grid reads this during a drag; a hidden card asks for nothing.","readonly":true},{"kind":"method","name":"hostChanged","description":"Called by the grid when its shape or its layout record changed."},{"kind":"method","name":"syncVisibility","privacy":"private","description":"Applies the layout record's `visible`. Hiding is deferred until the leave animation has played; showing again\ncancels a leave in flight and animates in. Before the first render, and outside a grid, nothing animates."},{"kind":"method","name":"dismiss","return":{"type":{"text":"Promise<void>"}},"description":"Plays the leave animation, then removes the element from the document. Resolves once it is gone. The other\ncards keep their placement — the grid does not close the gap; re-place them (`col`/`row` or the grid's\n`layout`) once the promise resolves if it should."},{"kind":"field","name":"surface","type":{"text":"HTMLElement | null"},"privacy":"private","readonly":true},{"kind":"method","name":"timing","privacy":"private","return":{"type":{"text":"{ duration: number; easing: string }"}},"parameters":[{"name":"target","type":{"text":"HTMLElement"}},{"name":"phase","type":{"text":"'enter' | 'leave'"}}],"description":"Enter and leave timing, read back from the stylesheet so the variables and `prefers-reduced-motion` apply."},{"kind":"method","name":"cancelMotion","privacy":"private"},{"kind":"method","name":"playEnter","privacy":"private"},{"kind":"method","name":"leave","privacy":"private","return":{"type":{"text":"Promise<boolean>"}},"description":"Fades the card out. Resolves `true` once it has finished — the caller then hides or removes the element — and\n`false` when a return cancelled it. The end state is held (`fill: forwards`) until the next enter cancels it,\nso nothing flashes between the last frame and the hide."},{"kind":"method","name":"syncHandleValues","privacy":"private","description":"The splitter values are written straight onto the handles rather than re-rendered: a drag changes them on\nevery pointer move, and nothing else about the card changes with them."},{"kind":"method","name":"attachToDashboard","privacy":"private","parameters":[{"name":"late","default":"true"}],"description":"The grid may upgrade after its cards do — the card element is in the document either way, so find it and wait\nfor the definition rather than for a parent that is already alive."},{"kind":"field","name":"placement","type":{"text":"EffectivePlacement"},"privacy":"private","readonly":true},{"kind":"method","name":"handleSlotChange","privacy":"private","parameters":[{"name":"event","type":{"text":"Event"}}]},{"kind":"method","name":"startDrag","privacy":"private","parameters":[{"name":"event","type":{"text":"PointerEvent"}},{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"index","type":{"text":"number"}}]},{"kind":"method","name":"handleHandleKeydown","privacy":"private","parameters":[{"name":"event","type":{"text":"KeyboardEvent"}},{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"index","type":{"text":"number"}}]},{"kind":"method","name":"toggleExpanded","privacy":"private","parameters":[{"name":"axis","type":{"text":"'width' | 'height' | 'full'"}}]},{"kind":"method","name":"renderControl","privacy":"private","parameters":[{"name":"axis","type":{"text":"'width' | 'height' | 'full'"}},{"name":"active","type":{"text":"boolean"}},{"name":"label","type":{"text":"string"}},{"name":"icon","type":{"text":"TemplateResult"}}]},{"kind":"method","name":"renderControls","privacy":"private"},{"kind":"method","name":"renderHandle","privacy":"private","parameters":[{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"edge","type":{"text":"'left' | 'right' | 'top' | 'bottom'"}},{"name":"index","type":{"text":"number"}}]},{"kind":"method","name":"renderHandles","privacy":"private"}],"events":[{"name":"expand-change","type":{"text":"CustomEvent<DashCardExpandChangeDetail>"},"description":"The card was expanded or collapsed through one of its own controls. Does not bubble: listen on the element."}],"attributes":[{"name":"card-id","type":{"text":"string | undefined"},"default":"undefined","description":"Identifier the grid's `layout` record is keyed by.","fieldName":"cardId"},{"name":"col","type":{"text":"number"},"default":"1","description":"1-based column the card starts in.","fieldName":"col"},{"name":"row","type":{"text":"number"},"default":"1","description":"1-based row the card starts in.","fieldName":"row"},{"name":"col-span","type":{"text":"number"},"default":"1","description":"Number of columns the card occupies.","fieldName":"colSpan"},{"name":"row-span","type":{"text":"number"},"default":"1","description":"Number of rows the card occupies.","fieldName":"rowSpan"},{"name":"min-width","type":{"text":"number"},"default":"0","description":"Smallest width in pixels the card accepts; it raises the minimum of every column it covers.","fieldName":"minWidth"},{"name":"min-height","type":{"text":"number"},"default":"0","description":"Smallest height in pixels the card accepts; it raises the minimum of every row it covers.","fieldName":"minHeight"},{"name":"resize","type":{"text":"DashCardResize"},"default":"'both'","description":"Which edges carry a drag handle.","fieldName":"resize"},{"name":"expand-width","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card across every column.","fieldName":"expandWidth"},{"name":"expand-height","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card across every row.","fieldName":"expandHeight"},{"name":"expand-full","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card over the whole grid.","fieldName":"expandFull"},{"name":"expanded","type":{"text":"DashCardExpanded"},"default":"'none'","description":"How far the card is currently expanded. Settable, so an app can expand a card from its own control.","fieldName":"expanded"}],"superclass":{"name":"LitElement","package":"lit"},"tagName":"c2-dash-card","customElement":true}],"exports":[{"kind":"js","name":"DashCard","declaration":{"name":"DashCard","module":"src/dash-card.ts"}},{"kind":"custom-element-definition","name":"c2-dash-card","declaration":{"name":"DashCard","module":"src/dash-card.ts"}}]}]}
1
+ {"schemaVersion":"1.0.0","readme":"","modules":[{"kind":"javascript-module","path":"src/dashboard.ts","declarations":[{"kind":"class","description":"Grid of resizable panes. The children are `c2-dash-card` elements, placed by their `col`/`row` attributes; each\none draws drag handles on the edges it shares with a neighbour, and dragging one resizes the whole track, so the\ncards on either side stay aligned. `columns` and `rows` take a track count (`columns=\"3\"` is three equal columns)\nor an explicit track list (`columns=\"320px 1fr\"`); a track is switched to pixels the first time it is dragged, and\nthe `fr` tracks around it give up the space in proportion to their weight, down to the minimums. With a\n`storage-key` the sizes survive a reload.\n\n`layouts` makes the grid responsive without a remount: each entry names a media query and the tracks and card\nplacements to use while it matches, the first match wins, and every entry keeps its own stored sizes under\n`<storage-key>@<media>`. Stored payloads are versioned and include stable card order; `serializeLayout` and\n`deserializeLayout` can preserve application metadata such as named sizes without coupling it to the component.\n\nPlacement is the application's: the grid never re-places cards on its own. A pane removed or hidden at runtime\nleaves its cells empty and its neighbours where they were, and a pane added at runtime lands exactly where its\n`col`/`row` say, on top of whatever is already there if that cell is taken. To close a gap, or to make room, set\nthe cards' `col`/`row`/`col-span`/`row-span` or hand the grid a `layout` record — both are applied in place.\n\nThe grid is the sizing authority: a card never sets its own width. Give the element a height (or place it in a\nflex/grid parent that does) whenever the rows use `fr`, since the row tracks divide the host's height.","name":"Dashboard","cssProperties":[{"type":{"text":"pixel"},"description":"Gutter between the cards. The whole gutter drags: each card's handle is centred on its edge and as thick as the gap (never under `--c2-dash-card__handle--size`).","name":"--c2-dashboard--gap","default":"8px"},{"type":{"text":"padding"},"description":"Inset around the tracks. With a `background` it is what turns the gutters into a visible frame between the panes.","name":"--c2-dashboard--padding","default":"0px"},{"type":{"text":"background"},"name":"--c2-dashboard--background","default":"transparent"},{"type":{"text":"border"},"name":"--c2-dashboard--border","default":"none"},{"type":{"text":"border-radius"},"name":"--c2-dashboard--border-radius","default":"0px"}],"slots":[{"description":"The `c2-dash-card` panes. Anything else becomes an ordinary grid item, placed by your own CSS.","name":""}],"members":[{"kind":"field","name":"columns","type":{"text":"number | string | string[]"},"default":"2","description":"Column count (`3`) or an explicit track list (`'320px 1fr'`). Each entry must be one simple size.","attribute":"columns"},{"kind":"field","name":"rows","type":{"text":"number | string | string[]"},"default":"1","description":"Row count (`2`) or an explicit track list (`'auto 1fr'`).","attribute":"rows"},{"kind":"field","name":"minColumnWidth","type":{"text":"number"},"default":"50","description":"Floor for every column, in pixels. A card's own `min-width` raises it for the tracks that card covers.","attribute":"min-column-width"},{"kind":"field","name":"minRowHeight","type":{"text":"number"},"default":"50","description":"Floor for every row, in pixels. A card's own `min-height` raises it for the tracks that card covers.","attribute":"min-row-height"},{"kind":"field","name":"storageKey","type":{"text":"string | undefined"},"default":"undefined","description":"`localStorage` key the track sizes and stable card order are stored under. Without it the grid starts from the authored layout.","attribute":"storage-key"},{"kind":"field","name":"layout","type":{"text":"Record<string, DashCardPlacement> | undefined"},"default":"undefined","description":"Placement overrides keyed by the cards' `card-id`, for a layout that is chosen at runtime rather than authored\nin the markup. Each entry wins over the card's own `col`/`row`/`col-span`/`row-span`/visibility. This is also\nhow an app re-flows the remaining panes after one was removed: the grid does not do that by itself."},{"kind":"field","name":"layouts","type":{"text":"DashboardResponsiveLayout[] | undefined"},"default":"undefined","description":"Responsive variants, in priority order: the first entry whose `media` matches supplies the tracks and the card\nplacements, and the grid switches as the viewport crosses a breakpoint. Nothing is stored across entries — each\none keeps its own sizes under `<storage-key>@<media>`."},{"kind":"field","name":"serializeLayout","type":{"text":"((layout: DashboardStoredLayout) => unknown) | undefined"},"default":"undefined","description":"Optional storage encoder. Use it to add application metadata such as named panel sizes."},{"kind":"field","name":"deserializeLayout","type":{"text":"((value: unknown) => DashboardStoredLayout | null) | undefined"},"default":"undefined","description":"Optional storage decoder paired with `serializeLayout`. It may also migrate older application payloads."},{"kind":"field","name":"columnTracks","type":{"text":"string[]"},"privacy":"private","default":"[]"},{"kind":"field","name":"rowTracks","type":{"text":"string[]"},"privacy":"private","default":"[]"},{"kind":"field","name":"activeLayout","type":{"text":"number"},"privacy":"private","default":"-1","description":"Index into `layouts` of the entry in force, `-1` for the authored grid."},{"kind":"field","name":"cards","privacy":"private","default":"new Set<DashboardCard>()"},{"kind":"field","name":"mediaQueries","type":{"text":"MediaQueryList[]"},"privacy":"private","default":"[]"},{"kind":"field","name":"handleMediaChange","privacy":"private","readonly":true},{"kind":"field","name":"pixelCache","privacy":"private","default":"new Map<'column' | 'row', number[]>()","description":"Used track sizes, valid until the next write to the tracks."},{"kind":"field","name":"columnSizes","type":{"text":"string[]"},"description":"Column tracks as they are laid out right now.","readonly":true},{"kind":"field","name":"rowSizes","type":{"text":"string[]"},"description":"Row tracks as they are laid out right now.","readonly":true},{"kind":"field","name":"columnCount","type":{"text":"number"},"readonly":true},{"kind":"field","name":"rowCount","type":{"text":"number"},"readonly":true},{"kind":"field","name":"activeResponsiveLayout","type":{"text":"DashboardResponsiveLayout | undefined"},"description":"The entry of `layouts` in force, or `undefined` while the authored grid is.","readonly":true},{"kind":"method","name":"reset","description":"Back to the authored tracks of the layout in force, and its stored ones are forgotten."},{"kind":"method","name":"registerCard","parameters":[{"name":"card","type":{"text":"DashboardCard"}}]},{"kind":"method","name":"unregisterCard","parameters":[{"name":"card","type":{"text":"DashboardCard"}}]},{"kind":"method","name":"placementOf","return":{"type":{"text":"DashCardPlacement | undefined"}},"parameters":[{"name":"cardId","type":{"text":"string | undefined"}}]},{"kind":"method","name":"resizeColumn","return":{"type":{"text":"number"}},"parameters":[{"name":"index","type":{"text":"number"}},{"name":"delta","type":{"text":"number"}}]},{"kind":"method","name":"resizeRow","return":{"type":{"text":"number"}},"parameters":[{"name":"index","type":{"text":"number"}},{"name":"delta","type":{"text":"number"}}]},{"kind":"method","name":"commitResize"},{"kind":"method","name":"setPanelOrder","parameters":[{"name":"order","type":{"text":"readonly string[]"}}],"description":"Reorders known cards by stable `card-id`, persists the order, and reports one layout change."},{"kind":"method","name":"splitterValue","return":{"type":{"text":"number"}},"parameters":[{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"index","type":{"text":"number"}}],"description":"Where the splitter after `index` sits, as a percentage of the tracks' total. A focusable `separator` is a\nwindow splitter, and a window splitter has to report a value."},{"kind":"method","name":"trackPixels","privacy":"private","return":{"type":{"text":"number[]"}},"parameters":[{"name":"axis","type":{"text":"'column' | 'row'"}}],"description":"Reading a used track size forces layout, and a drag asks for it from every card's handles on every pointer\nmove. The answer cannot change until something writes to the DOM, so it is cached until one of them does."},{"kind":"method","name":"freeSpace","privacy":"private","return":{"type":{"text":"number"}},"parameters":[{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"tracks","type":{"text":"number[]"}}],"description":"What is left of the host along `axis` once the tracks, the gutters and the padding have taken their share."},{"kind":"method","name":"emitLayoutChange","privacy":"private"},{"kind":"method","name":"resizeTrack","privacy":"private","return":{"type":{"text":"{ tracks: string[]; applied: number } | undefined"}},"parameters":[{"name":"tracks","type":{"text":"string[]"}},{"name":"index","type":{"text":"number"}},{"name":"delta","type":{"text":"number"}},{"name":"axis","type":{"text":"'column' | 'row'"}}]},{"kind":"method","name":"trackMin","privacy":"private","return":{"type":{"text":"number"}},"parameters":[{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"index","type":{"text":"number"}}],"description":"The largest minimum any card covering this track asks for, spread over the tracks that card spans."},{"kind":"method","name":"watchMedia","privacy":"private","description":"One `MediaQueryList` per entry of `layouts`, listened to for as long as the element is connected. Whichever\nentry matches first is the one in force; the listeners re-run the choice whenever any of them flips."},{"kind":"method","name":"unwatchMedia","privacy":"private"},{"kind":"method","name":"resolveActiveLayout","privacy":"private","return":{"type":{"text":"number"}}},{"kind":"field","name":"activeStorageKey","type":{"text":"string | undefined"},"privacy":"private","description":"Each entry of `layouts` stores its own sizes: `<storage-key>@<media>`; the authored grid uses the bare key.","readonly":true},{"kind":"method","name":"syncTracks","privacy":"private"},{"kind":"method","name":"readStored","privacy":"private","return":{"type":{"text":"DashboardStoredLayout | null"}}},{"kind":"method","name":"persist","privacy":"private"},{"kind":"field","name":"panelOrder","type":{"text":"string[]"},"privacy":"private","readonly":true},{"kind":"method","name":"applyPanelOrder","privacy":"private","parameters":[{"name":"order","type":{"text":"readonly string[]"}}]}],"events":[{"name":"layout-change","type":{"text":"CustomEvent<DashboardLayoutChangeDetail>"},"description":"The tracks or stable card order changed: a gesture ended, `setPanelOrder()`/`reset()` was called, or another entry of `layouts` took over. Includes the active breakpoint. Does not bubble: listen on the element."}],"attributes":[{"name":"columns","type":{"text":"number | string | string[]"},"default":"2","description":"Column count (`3`) or an explicit track list (`'320px 1fr'`). Each entry must be one simple size.","fieldName":"columns"},{"name":"rows","type":{"text":"number | string | string[]"},"default":"1","description":"Row count (`2`) or an explicit track list (`'auto 1fr'`).","fieldName":"rows"},{"name":"min-column-width","type":{"text":"number"},"default":"50","description":"Floor for every column, in pixels. A card's own `min-width` raises it for the tracks that card covers.","fieldName":"minColumnWidth"},{"name":"min-row-height","type":{"text":"number"},"default":"50","description":"Floor for every row, in pixels. A card's own `min-height` raises it for the tracks that card covers.","fieldName":"minRowHeight"},{"name":"storage-key","type":{"text":"string | undefined"},"default":"undefined","description":"`localStorage` key the track sizes and stable card order are stored under. Without it the grid starts from the authored layout.","fieldName":"storageKey"}],"superclass":{"name":"LitElement","package":"lit"},"tagName":"c2-dashboard","customElement":true}],"exports":[{"kind":"js","name":"DashCardPlacement","declaration":{"name":"DashCardPlacement","module":"./dashboard-host"}},{"kind":"js","name":"Dashboard","declaration":{"name":"Dashboard","module":"src/dashboard.ts"}},{"kind":"custom-element-definition","name":"c2-dashboard","declaration":{"name":"Dashboard","module":"src/dashboard.ts"}}]},{"kind":"javascript-module","path":"src/dash-card.ts","declarations":[{"kind":"class","description":"One pane of a `c2-dashboard`. It owns its place in the grid (`col`, `row`, `col-span`, `row-span`), the drag\nhandles on the edges it shares with a neighbour, and the optional expand controls; it draws no surface of its\nown, so put a `c2-card` — or any markup — in the default slot.\n\nA handle resizes the whole grid track, never just this card, and it only appears where there is a neighbour to\ntake the space from: the right edge has one when another column follows, the left edge when one precedes. Drag\nit, or focus it and use the arrow keys (10px a step, 1px with Shift).\n\nFilling the `header`, `actions` or `footer` slot turns on that row; with the header and actions both empty the\nexpand controls float over the top-right corner of the pane instead. An expanded card covers its neighbours on\nan opaque `--c2-dash-card__expanded--background` (the theme's surface colour), while the card itself stays\ntransparent at rest.\n\nA card that arrives while the grid is already on screen fades and scales in; one that leaves — through the\ngrid's `layout` record (`visible: false`) or through `dismiss()`, which removes the element once the animation\nhas played — fades out the same way. Cards present at load do not animate, and `prefers-reduced-motion` turns\nboth off.\n\nEvery built-in icon is a slot whose fallback is the default drawing, so a pane can use the host application's own\nicon set without giving up the behaviour.","name":"DashCard","cssProperties":[{"type":{"text":"background"},"name":"--c2-dash-card--background","default":"transparent"},{"type":{"text":"border"},"name":"--c2-dash-card--border","default":"none"},{"type":{"text":"border-radius"},"name":"--c2-dash-card--border-radius","default":"0px"},{"type":{"text":"box-shadow"},"name":"--c2-dash-card--box-shadow","default":"none"},{"type":{"text":"padding"},"name":"--c2-dash-card--padding","default":"0px"},{"type":{"text":"overflow"},"description":"`hidden` keeps the content inside the track; switch it to `visible` for a pane that has to overflow, such as one holding a menu.","name":"--c2-dash-card--overflow","default":"hidden"},{"type":{"text":"background"},"description":"Fill while the card is expanded over its neighbours, so they do not show through; the card's own `background` stays transparent.","name":"--c2-dash-card__expanded--background","default":"#ffffff"},{"type":{"text":"number"},"name":"--c2-dash-card__expanded--z-index","default":"20"},{"type":{"text":"duration"},"description":"Fade and scale-in of a card added to a grid that is already on screen, or shown again through the layout record. `0ms` disables it.","name":"--c2-dash-card__enter--animation-duration","default":"200ms"},{"type":{"text":"duration"},"description":"Fade-out before a card is hidden by the layout record or removed by `dismiss()`. `0ms` disables it.","name":"--c2-dash-card__leave--animation-duration","default":"160ms"},{"type":{"text":"duration"},"description":"Length of the scale-in the card plays when it expands or collapses. Ignored under `prefers-reduced-motion`.","name":"--c2-dash-card__expanded--animation-duration","default":"200ms"},{"type":{"text":"pixel"},"name":"--c2-dash-card__header--min-height","default":"44px"},{"type":{"text":"padding"},"name":"--c2-dash-card__header--padding-block","default":"8px"},{"type":{"text":"padding"},"name":"--c2-dash-card__header--padding-inline","default":"12px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__header--gap","default":"12px"},{"type":{"text":"background"},"name":"--c2-dash-card__header--background","default":"transparent"},{"type":{"text":"border"},"name":"--c2-dash-card__header--border-bottom","default":"none"},{"type":{"text":"color"},"name":"--c2-dash-card__header--color","default":"#18181b"},{"type":{"text":"pixel"},"name":"--c2-dash-card__header--font-size","default":"14px"},{"type":{"text":"font-weight"},"name":"--c2-dash-card__header--font-weight","default":"600"},{"type":{"text":"pixel"},"name":"--c2-dash-card__footer--min-height","default":"36px"},{"type":{"text":"padding"},"name":"--c2-dash-card__footer--padding-block","default":"6px"},{"type":{"text":"padding"},"name":"--c2-dash-card__footer--padding-inline","default":"12px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__footer--gap","default":"8px"},{"type":{"text":"background"},"name":"--c2-dash-card__footer--background","default":"transparent"},{"type":{"text":"border"},"name":"--c2-dash-card__footer--border-top","default":"none"},{"type":{"text":"color"},"name":"--c2-dash-card__footer--color","default":"#71717a"},{"type":{"text":"pixel"},"name":"--c2-dash-card__footer--font-size","default":"12px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__actions--gap","default":"8px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__controls--gap","default":"2px"},{"type":{"text":"pixel"},"description":"Inset of the floating control group from the top-right corner, used only while the header row is off.","name":"--c2-dash-card__controls--offset","default":"4px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__control--size","default":"24px"},{"type":{"text":"pixel"},"name":"--c2-dash-card__control--icon-size","default":"16px"},{"type":{"text":"border-radius"},"name":"--c2-dash-card__control--border-radius","default":"6px"},{"type":{"text":"color"},"name":"--c2-dash-card__control--color","default":"#71717a"},{"type":{"text":"background"},"name":"--c2-dash-card__control--background","default":"transparent"},{"type":{"text":"background"},"name":"--c2-dash-card__control__hover--background","default":"#f4f4f5"},{"type":{"text":"color"},"name":"--c2-dash-card__control__hover--color","default":"#18181b"},{"type":{"text":"outline"},"name":"--c2-dash-card__control__focus--outline","default":"2px solid rgba(2, 101, 220, 0.4)"},{"type":{"text":"pixel"},"name":"--c2-dash-card__control__focus--outline-offset","default":"2px"},{"type":{"text":"pixel"},"description":"Smallest thickness of the grab area on an edge. Inside a grid the handle is as thick as the gutter when that is wider, centred on the edge, so the whole gutter drags.","name":"--c2-dash-card__handle--size","default":"6px"},{"type":{"text":"pixel"},"description":"Gap between the handle's visible bar and the ends of the edge.","name":"--c2-dash-card__handle--inset","default":"2px"},{"type":{"text":"background"},"name":"--c2-dash-card__handle--background","default":"transparent"},{"type":{"text":"background"},"name":"--c2-dash-card__handle__hover--background","default":"rgba(2, 101, 220, 0.2)"},{"type":{"text":"background"},"name":"--c2-dash-card__handle__active--background","default":"rgb(2, 101, 220)"},{"type":{"text":"border-radius"},"name":"--c2-dash-card__handle--border-radius","default":"999px"},{"type":{"text":"duration"},"name":"--c2-dash-card__handle--transition-duration","default":"150ms"},{"type":{"text":"outline"},"name":"--c2-dash-card__handle__focus--outline","default":"2px solid rgba(2, 101, 220, 0.4)"}],"cssParts":[{"description":"Conditional row containing the `header` and `actions` slots, or the floating controls when both are empty.","name":"header"},{"description":"The wrapper around the default slot.","name":"body"},{"description":"Conditional row wrapping the assigned `footer` slot.","name":"footer"},{"description":"Component-owned group containing the `controls` slot and built-in expand-button fallbacks.","name":"controls"},{"description":"One built-in expand button.","name":"control"},{"description":"Every drag handle. Each also carries the part of its edge.","name":"handle"},{"description":"The handle on the left edge.","name":"handle-left"},{"description":"The handle on the right edge.","name":"handle-right"},{"description":"The handle on the top edge.","name":"handle-top"},{"description":"The handle on the bottom edge.","name":"handle-bottom"}],"slots":[{"description":"Pane content. It fills the pane: the body is a column flex box and every slotted child is a `flex: 1` item with `min-height: 0`, so a chart or an editor follows the row track without a `height: 100%` chain.","name":""},{"description":"Title area of the header row; filling it turns the row on.","name":"header"},{"description":"Your own controls at the end of the header row, before the built-in expand buttons and separated from them by `--c2-dash-card__actions--gap`.","name":"actions"},{"description":"Your own controls inside the built-in group, immediately before the expand buttons — for a button that belongs with them, such as a refresh or a close.","name":"controls"},{"description":"Status bar under the pane content; filling it turns the row on.","name":"footer"},{"description":"Icon of the full-width control while the card is not expanded that way.","name":"expand-width-icon"},{"description":"Icon of the full-width control while it is.","name":"collapse-width-icon"},{"description":"Icon of the full-height control while the card is not expanded that way.","name":"expand-height-icon"},{"description":"Icon of the full-height control while it is.","name":"collapse-height-icon"},{"description":"Icon of the fullscreen control while the card is not expanded.","name":"expand-full-icon"},{"description":"Icon of the fullscreen control while it is.","name":"collapse-full-icon"}],"members":[{"kind":"field","name":"cardId","type":{"text":"string | undefined"},"default":"undefined","description":"Identifier the grid's `layout` record is keyed by.","attribute":"card-id"},{"kind":"field","name":"col","type":{"text":"number"},"default":"1","description":"1-based column the card starts in.","attribute":"col"},{"kind":"field","name":"row","type":{"text":"number"},"default":"1","description":"1-based row the card starts in.","attribute":"row"},{"kind":"field","name":"colSpan","type":{"text":"number"},"default":"1","description":"Number of columns the card occupies.","attribute":"col-span"},{"kind":"field","name":"rowSpan","type":{"text":"number"},"default":"1","description":"Number of rows the card occupies.","attribute":"row-span"},{"kind":"field","name":"minWidth","type":{"text":"number"},"default":"0","description":"Smallest width in pixels the card accepts; it raises the minimum of every column it covers.","attribute":"min-width"},{"kind":"field","name":"minHeight","type":{"text":"number"},"default":"0","description":"Smallest height in pixels the card accepts; it raises the minimum of every row it covers.","attribute":"min-height"},{"kind":"field","name":"resize","type":{"text":"DashCardResize"},"default":"'both'","description":"Which edges carry a drag handle.","attribute":"resize","reflects":true},{"kind":"field","name":"expandWidth","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card across every column.","attribute":"expand-width"},{"kind":"field","name":"expandHeight","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card across every row.","attribute":"expand-height"},{"kind":"field","name":"expandFull","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card over the whole grid.","attribute":"expand-full"},{"kind":"field","name":"expanded","type":{"text":"DashCardExpanded"},"default":"'none'","description":"How far the card is currently expanded. Settable, so an app can expand a card from its own control.","attribute":"expanded","reflects":true},{"kind":"field","name":"slotPresence","privacy":"private","readonly":true,"default":"new SlotPresenceController(this, ['header', 'actions', 'controls', 'footer'])"},{"kind":"field","name":"dashboard","type":{"text":"DashboardHost | undefined"},"privacy":"private","default":"undefined"},{"kind":"field","name":"leaving","type":{"text":"boolean"},"privacy":"private","default":"false","description":"`true` while the leave animation plays: the handles are gone, the placement is kept until it ends."},{"kind":"field","name":"motion","type":{"text":"Animation | undefined"},"privacy":"private","description":"The enter or leave animation in flight — or the finished leave, kept so a return can cancel its fill."},{"kind":"field","name":"enterPending","type":{"text":"boolean"},"privacy":"private","default":"false","description":"Set when the card should animate in after its next render."},{"kind":"field","name":"constraint","type":{"text":"DashCardConstraint | undefined"},"description":"The grid reads this during a drag; a hidden card asks for nothing.","readonly":true},{"kind":"method","name":"hostChanged","description":"Called by the grid when its shape or its layout record changed."},{"kind":"method","name":"syncVisibility","privacy":"private","description":"Applies the layout record's `visible`. Hiding is deferred until the leave animation has played; showing again\ncancels a leave in flight and animates in. Before the first render, and outside a grid, nothing animates."},{"kind":"method","name":"dismiss","return":{"type":{"text":"Promise<void>"}},"description":"Plays the leave animation, then removes the element from the document. Resolves once it is gone. The other\ncards keep their placement — the grid does not close the gap; re-place them (`col`/`row` or the grid's\n`layout`) once the promise resolves if it should."},{"kind":"field","name":"surface","type":{"text":"HTMLElement | null"},"privacy":"private","readonly":true},{"kind":"method","name":"timing","privacy":"private","return":{"type":{"text":"{ duration: number; easing: string }"}},"parameters":[{"name":"target","type":{"text":"HTMLElement"}},{"name":"phase","type":{"text":"'enter' | 'leave'"}}],"description":"Enter and leave timing, read back from the stylesheet so the variables and `prefers-reduced-motion` apply."},{"kind":"method","name":"cancelMotion","privacy":"private"},{"kind":"method","name":"playEnter","privacy":"private"},{"kind":"method","name":"leave","privacy":"private","return":{"type":{"text":"Promise<boolean>"}},"description":"Fades the card out. Resolves `true` once it has finished — the caller then hides or removes the element — and\n`false` when a return cancelled it. The end state is held (`fill: forwards`) until the next enter cancels it,\nso nothing flashes between the last frame and the hide."},{"kind":"method","name":"syncHandleValues","privacy":"private","description":"The splitter values are written straight onto the handles rather than re-rendered: a drag changes them on\nevery pointer move, and nothing else about the card changes with them."},{"kind":"method","name":"attachToDashboard","privacy":"private","parameters":[{"name":"late","default":"true"}],"description":"The grid may upgrade after its cards do — the card element is in the document either way, so find it and wait\nfor the definition rather than for a parent that is already alive."},{"kind":"field","name":"placement","type":{"text":"EffectivePlacement"},"privacy":"private","readonly":true},{"kind":"method","name":"handleSlotChange","privacy":"private","parameters":[{"name":"event","type":{"text":"Event"}}]},{"kind":"method","name":"startDrag","privacy":"private","parameters":[{"name":"event","type":{"text":"PointerEvent"}},{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"index","type":{"text":"number"}}]},{"kind":"method","name":"handleHandleKeydown","privacy":"private","parameters":[{"name":"event","type":{"text":"KeyboardEvent"}},{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"index","type":{"text":"number"}}]},{"kind":"method","name":"toggleExpanded","privacy":"private","parameters":[{"name":"axis","type":{"text":"'width' | 'height' | 'full'"}}]},{"kind":"method","name":"renderControl","privacy":"private","parameters":[{"name":"axis","type":{"text":"'width' | 'height' | 'full'"}},{"name":"active","type":{"text":"boolean"}},{"name":"label","type":{"text":"string"}},{"name":"icon","type":{"text":"TemplateResult"}}]},{"kind":"method","name":"renderControls","privacy":"private"},{"kind":"method","name":"renderHandle","privacy":"private","parameters":[{"name":"axis","type":{"text":"'column' | 'row'"}},{"name":"edge","type":{"text":"'left' | 'right' | 'top' | 'bottom'"}},{"name":"index","type":{"text":"number"}}]},{"kind":"method","name":"renderHandles","privacy":"private"}],"events":[{"name":"expand-change","type":{"text":"CustomEvent<DashCardExpandChangeDetail>"},"description":"The card was expanded or collapsed through one of its own controls. Does not bubble: listen on the element."}],"attributes":[{"name":"card-id","type":{"text":"string | undefined"},"default":"undefined","description":"Identifier the grid's `layout` record is keyed by.","fieldName":"cardId"},{"name":"col","type":{"text":"number"},"default":"1","description":"1-based column the card starts in.","fieldName":"col"},{"name":"row","type":{"text":"number"},"default":"1","description":"1-based row the card starts in.","fieldName":"row"},{"name":"col-span","type":{"text":"number"},"default":"1","description":"Number of columns the card occupies.","fieldName":"colSpan"},{"name":"row-span","type":{"text":"number"},"default":"1","description":"Number of rows the card occupies.","fieldName":"rowSpan"},{"name":"min-width","type":{"text":"number"},"default":"0","description":"Smallest width in pixels the card accepts; it raises the minimum of every column it covers.","fieldName":"minWidth"},{"name":"min-height","type":{"text":"number"},"default":"0","description":"Smallest height in pixels the card accepts; it raises the minimum of every row it covers.","fieldName":"minHeight"},{"name":"resize","type":{"text":"DashCardResize"},"default":"'both'","description":"Which edges carry a drag handle.","fieldName":"resize"},{"name":"expand-width","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card across every column.","fieldName":"expandWidth"},{"name":"expand-height","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card across every row.","fieldName":"expandHeight"},{"name":"expand-full","type":{"text":"boolean"},"default":"false","description":"Offers a control that expands the card over the whole grid.","fieldName":"expandFull"},{"name":"expanded","type":{"text":"DashCardExpanded"},"default":"'none'","description":"How far the card is currently expanded. Settable, so an app can expand a card from its own control.","fieldName":"expanded"}],"superclass":{"name":"LitElement","package":"lit"},"tagName":"c2-dash-card","customElement":true}],"exports":[{"kind":"js","name":"DashCard","declaration":{"name":"DashCard","module":"src/dash-card.ts"}},{"kind":"custom-element-definition","name":"c2-dash-card","declaration":{"name":"DashCard","module":"src/dash-card.ts"}}]}]}
package/dist/dashboard.js CHANGED
@@ -40,6 +40,8 @@ var Dashboard = class Dashboard extends LitElement {
40
40
  this.storageKey = void 0;
41
41
  this.layout = void 0;
42
42
  this.layouts = void 0;
43
+ this.serializeLayout = void 0;
44
+ this.deserializeLayout = void 0;
43
45
  this.columnTracks = [];
44
46
  this.rowTracks = [];
45
47
  this.activeLayout = -1;
@@ -134,6 +136,12 @@ var Dashboard = class Dashboard extends LitElement {
134
136
  this.persist();
135
137
  this.emitLayoutChange();
136
138
  }
139
+ /** Reorders known cards by stable `card-id`, persists the order, and reports one layout change. */
140
+ setPanelOrder(order) {
141
+ this.applyPanelOrder(order);
142
+ this.persist();
143
+ this.emitLayoutChange();
144
+ }
137
145
  /**
138
146
  * Where the splitter after `index` sits, as a percentage of the tracks' total. A focusable `separator` is a
139
147
  * window splitter, and a window splitter has to report a value.
@@ -170,7 +178,9 @@ var Dashboard = class Dashboard extends LitElement {
170
178
  this.dispatchEvent(new CustomEvent("layout-change", {
171
179
  detail: {
172
180
  columns: [...this.columnTracks],
173
- rows: [...this.rowTracks]
181
+ rows: [...this.rowTracks],
182
+ order: this.panelOrder,
183
+ breakpoint: this.activeResponsiveLayout?.media ?? null
174
184
  },
175
185
  bubbles: false,
176
186
  composed: true
@@ -256,6 +266,7 @@ var Dashboard = class Dashboard extends LitElement {
256
266
  const stored = this.readStored();
257
267
  this.columnTracks = stored?.columns?.length === columns.length ? [...stored.columns] : columns;
258
268
  this.rowTracks = stored?.rows?.length === rows.length ? [...stored.rows] : rows;
269
+ if (stored?.order?.length) queueMicrotask(() => this.applyPanelOrder(stored.order));
259
270
  }
260
271
  readStored() {
261
272
  const key = this.activeStorageKey;
@@ -264,6 +275,7 @@ var Dashboard = class Dashboard extends LitElement {
264
275
  const raw = localStorage.getItem(key);
265
276
  if (!raw) return null;
266
277
  const parsed = JSON.parse(raw);
278
+ if (this.deserializeLayout) return this.deserializeLayout(parsed);
267
279
  return parsed && typeof parsed === "object" ? parsed : null;
268
280
  } catch {
269
281
  return null;
@@ -273,15 +285,30 @@ var Dashboard = class Dashboard extends LitElement {
273
285
  const key = this.activeStorageKey;
274
286
  if (!key || isServer) return;
275
287
  try {
276
- localStorage.setItem(key, JSON.stringify({
277
- columns: this.columnTracks,
278
- rows: this.rowTracks
279
- }));
288
+ const layout = {
289
+ version: 1,
290
+ columns: [...this.columnTracks],
291
+ rows: [...this.rowTracks],
292
+ order: this.panelOrder,
293
+ breakpoint: this.activeResponsiveLayout?.media ?? null
294
+ };
295
+ localStorage.setItem(key, JSON.stringify(this.serializeLayout ? this.serializeLayout(layout) : layout));
280
296
  } catch {}
281
297
  }
282
298
  render() {
283
299
  return html`<slot></slot>`;
284
300
  }
301
+ get panelOrder() {
302
+ return [...this.children].filter((child) => child instanceof HTMLElement && child.tagName.toLowerCase() === "c2-dash-card").map((card) => card.cardId ?? card.getAttribute("card-id") ?? "").filter(Boolean);
303
+ }
304
+ applyPanelOrder(order) {
305
+ const cards = [...this.children].filter((child) => child instanceof HTMLElement && child.tagName.toLowerCase() === "c2-dash-card");
306
+ const byId = new Map(cards.map((card) => [card.cardId ?? card.getAttribute("card-id") ?? "", card]));
307
+ const ordered = order.map((id) => byId.get(id)).filter((card) => Boolean(card));
308
+ for (const card of cards) if (!ordered.includes(card)) ordered.push(card);
309
+ if (ordered.every((card, index) => card === cards[index])) return;
310
+ this.append(...ordered);
311
+ }
285
312
  };
286
313
  __decorate([property()], Dashboard.prototype, "columns", void 0);
287
314
  __decorate([property()], Dashboard.prototype, "rows", void 0);
@@ -296,6 +323,8 @@ __decorate([property({
296
323
  __decorate([property({ attribute: "storage-key" })], Dashboard.prototype, "storageKey", void 0);
297
324
  __decorate([property({ attribute: false })], Dashboard.prototype, "layout", void 0);
298
325
  __decorate([property({ attribute: false })], Dashboard.prototype, "layouts", void 0);
326
+ __decorate([property({ attribute: false })], Dashboard.prototype, "serializeLayout", void 0);
327
+ __decorate([property({ attribute: false })], Dashboard.prototype, "deserializeLayout", void 0);
299
328
  __decorate([state()], Dashboard.prototype, "columnTracks", void 0);
300
329
  __decorate([state()], Dashboard.prototype, "rowTracks", void 0);
301
330
  __decorate([state()], Dashboard.prototype, "activeLayout", void 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c2n/dashboard",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "type": "module",
5
5
  "main": "dist/dashboard.js",
6
6
  "exports": {
@@ -74,12 +74,12 @@
74
74
  }
75
75
  },
76
76
  "dependencies": {
77
- "@c2n/core": "0.0.14",
77
+ "@c2n/core": "0.0.16",
78
78
  "lit": "3.3.3"
79
79
  },
80
80
  "devDependencies": {
81
81
  "@c2n/config": "*"
82
82
  },
83
83
  "customElements": "custom-elements.json",
84
- "gitHead": "0261bfceaaa9f710a54e8f36cb57f946c0b83e53"
84
+ "gitHead": "d04bcc1c278febafc95f94904d68ea583d380e05"
85
85
  }
package/react.d.ts CHANGED
@@ -9,7 +9,8 @@
9
9
  //
10
10
  // On a server-rendered page (Next.js, React Router SSR) write a camelCase property by its kebab-case attribute
11
11
  // name ('row-key', not rowKey): the server emits props verbatim, HTML lowercases them, and hydration does not
12
- // set properties. Those names are listed next to the properties below.
12
+ // set properties. Those names are listed next to the properties below. Structured converter-backed values
13
+ // also accept their serialized string form, so server JSX can emit the same JSON/CSV attribute used by HTML.
13
14
 
14
15
  import type { DetailedHTMLProps, HTMLAttributes } from 'react'
15
16
  import type { DashCard } from '@c2n/dashboard/dash-card.js'
@@ -33,10 +34,12 @@ declare module 'react' {
33
34
  'expand-height'?: Attribute
34
35
  'expand-full'?: Attribute
35
36
  }
36
- 'c2-dashboard': C2Props<Dashboard> & {
37
+ 'c2-dashboard': Omit<C2Props<Dashboard>, 'columns' | 'rows'> & {
37
38
  'min-column-width'?: Attribute
38
39
  'min-row-height'?: Attribute
39
40
  'storage-key'?: Attribute
41
+ columns?: Dashboard['columns'] | string
42
+ rows?: Dashboard['rows'] | string
40
43
  }
41
44
  }
42
45
  }
@@ -44,6 +44,8 @@ export interface DashboardHost extends HTMLElement {
44
44
  }
45
45
  /** The part of `c2-dash-card` the grid reads back. */
46
46
  export interface DashboardCard extends HTMLElement {
47
+ /** Stable persistence identity supplied by the card's `card-id`. */
48
+ readonly cardId?: string;
47
49
  /** `undefined` while the card is hidden, so a hidden card constrains nothing. */
48
50
  readonly constraint: DashCardConstraint | undefined;
49
51
  /** The grid changed shape: re-render the placement and the handles. */
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-host.d.ts","sourceRoot":"","sources":["../../src/dashboard-host.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oGAAoG;AACpG,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sGAAsG;IACtG,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,iGAAiG;AACjG,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,kDAAkD;AAClD,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,8GAA8G;IAC9G,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAAA;IACvC,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAAA;IACzC,mHAAmH;IACnH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IAClD,gHAAgH;IAChH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IAC/C,iEAAiE;IACjE,YAAY,IAAI,IAAI,CAAA;IACpB,kHAAkH;IAClH,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IAC5D,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,CAAA;CACvE;AAED,sDAAsD;AACtD,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,iFAAiF;IACjF,QAAQ,CAAC,UAAU,EAAE,kBAAkB,GAAG,SAAS,CAAA;IACnD,uEAAuE;IACvE,WAAW,IAAI,IAAI,CAAA;CACpB;AAED,eAAO,MAAM,aAAa,iBAAiB,CAAA"}
1
+ {"version":3,"file":"dashboard-host.d.ts","sourceRoot":"","sources":["../../src/dashboard-host.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oGAAoG;AACpG,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,sCAAsC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sGAAsG;IACtG,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,iGAAiG;AACjG,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,kDAAkD;AAClD,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,8GAA8G;IAC9G,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAAA;IACvC,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAAA;IACzC,mHAAmH;IACnH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IAClD,gHAAgH;IAChH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IAC/C,iEAAiE;IACjE,YAAY,IAAI,IAAI,CAAA;IACpB,kHAAkH;IAClH,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IAC5D,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,CAAA;CACvE;AAED,sDAAsD;AACtD,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,oEAAoE;IACpE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,iFAAiF;IACjF,QAAQ,CAAC,UAAU,EAAE,kBAAkB,GAAG,SAAS,CAAA;IACnD,uEAAuE;IACvE,WAAW,IAAI,IAAI,CAAA;CACpB;AAED,eAAO,MAAM,aAAa,iBAAiB,CAAA"}
@@ -9,6 +9,10 @@ export interface DashboardLayoutChangeDetail {
9
9
  columns: string[];
10
10
  /** Row tracks. */
11
11
  rows: string[];
12
+ /** Stable card IDs in DOM and reading order. */
13
+ order: string[];
14
+ /** Active responsive media query, or `null` for the authored layout. */
15
+ breakpoint: string | null;
12
16
  }
13
17
  /** Events fired by {@link Dashboard}, keyed for `addEventListener`. */
14
18
  export interface DashboardEventMap {
@@ -32,6 +36,13 @@ export interface DashboardResponsiveLayout {
32
36
  /** Placement overrides by `card-id`, merged per card over the grid's `layout`. */
33
37
  layout?: Record<string, DashCardPlacement>;
34
38
  }
39
+ export interface DashboardStoredLayout {
40
+ version?: 1;
41
+ columns?: string[];
42
+ rows?: string[];
43
+ order?: string[];
44
+ breakpoint?: string | null;
45
+ }
35
46
  /**
36
47
  * Grid of resizable panes. The children are `c2-dash-card` elements, placed by their `col`/`row` attributes; each
37
48
  * one draws drag handles on the edges it shares with a neighbour, and dragging one resizes the whole track, so the
@@ -42,7 +53,8 @@ export interface DashboardResponsiveLayout {
42
53
  *
43
54
  * `layouts` makes the grid responsive without a remount: each entry names a media query and the tracks and card
44
55
  * placements to use while it matches, the first match wins, and every entry keeps its own stored sizes under
45
- * `<storage-key>@<media>`.
56
+ * `<storage-key>@<media>`. Stored payloads are versioned and include stable card order; `serializeLayout` and
57
+ * `deserializeLayout` can preserve application metadata such as named sizes without coupling it to the component.
46
58
  *
47
59
  * Placement is the application's: the grid never re-places cards on its own. A pane removed or hidden at runtime
48
60
  * leaves its cells empty and its neighbours where they were, and a pane added at runtime lands exactly where its
@@ -56,8 +68,9 @@ export interface DashboardResponsiveLayout {
56
68
  *
57
69
  * @slot - The `c2-dash-card` panes. Anything else becomes an ordinary grid item, placed by your own CSS.
58
70
  *
59
- * @event {CustomEvent<DashboardLayoutChangeDetail>} layout-change - The track sizes changed: a gesture ended, `reset()`
60
- * was called, or another entry of `layouts` took over. Does not bubble: listen on the element.
71
+ * @event {CustomEvent<DashboardLayoutChangeDetail>} layout-change - The tracks or stable card order changed: a
72
+ * gesture ended, `setPanelOrder()`/`reset()` was called, or another entry of `layouts` took over. Includes the active
73
+ * breakpoint. Does not bubble: listen on the element.
61
74
  *
62
75
  * @cssproperty {pixel} [--c2-dashboard--gap=8px] - Gutter between the cards. The whole gutter drags: each card's
63
76
  * handle is centred on its edge and as thick as the gap (never under `--c2-dash-card__handle--size`).
@@ -77,7 +90,7 @@ export declare class Dashboard extends LitElement {
77
90
  minColumnWidth: number;
78
91
  /** Floor for every row, in pixels. A card's own `min-height` raises it for the tracks that card covers. */
79
92
  minRowHeight: number;
80
- /** `localStorage` key the track sizes are stored under. Without it the grid starts from the authored tracks. */
93
+ /** `localStorage` key the track sizes and stable card order are stored under. Without it the grid starts from the authored layout. */
81
94
  storageKey: string | undefined;
82
95
  /**
83
96
  * Placement overrides keyed by the cards' `card-id`, for a layout that is chosen at runtime rather than authored
@@ -91,6 +104,10 @@ export declare class Dashboard extends LitElement {
91
104
  * one keeps its own sizes under `<storage-key>@<media>`.
92
105
  */
93
106
  layouts: DashboardResponsiveLayout[] | undefined;
107
+ /** Optional storage encoder. Use it to add application metadata such as named panel sizes. */
108
+ serializeLayout: ((layout: DashboardStoredLayout) => unknown) | undefined;
109
+ /** Optional storage decoder paired with `serializeLayout`. It may also migrate older application payloads. */
110
+ deserializeLayout: ((value: unknown) => DashboardStoredLayout | null) | undefined;
94
111
  private columnTracks;
95
112
  private rowTracks;
96
113
  /** Index into `layouts` of the entry in force, `-1` for the authored grid. */
@@ -120,6 +137,8 @@ export declare class Dashboard extends LitElement {
120
137
  resizeColumn(index: number, delta: number): number;
121
138
  resizeRow(index: number, delta: number): number;
122
139
  commitResize(): void;
140
+ /** Reorders known cards by stable `card-id`, persists the order, and reports one layout change. */
141
+ setPanelOrder(order: readonly string[]): void;
123
142
  /**
124
143
  * Where the splitter after `index` sits, as a percentage of the tracks' total. A focusable `separator` is a
125
144
  * window splitter, and a window splitter has to report a value.
@@ -149,6 +168,8 @@ export declare class Dashboard extends LitElement {
149
168
  private readStored;
150
169
  private persist;
151
170
  render(): import("lit-html").TemplateResult<1>;
171
+ private get panelOrder();
172
+ private applyPanelOrder;
152
173
  }
153
174
  declare global {
154
175
  interface HTMLElementTagNameMap {
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/dashboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAA;AAKtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAA;AAChG,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAIxE,OAAO,aAAa,CAAA;AAEpB,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD,4FAA4F;AAC5F,MAAM,WAAW,2BAA2B;IAC1C,8CAA8C;IAC9C,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,kBAAkB;IAClB,IAAI,EAAE,MAAM,EAAE,CAAA;CACf;AAED,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,WAAW,CAAC,2BAA2B,CAAC,CAAA;CAC1D;AAED,MAAM,WAAW,SAAS;IACxB,gBAAgB,EAAE,qBAAqB,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAA;IACrE,mBAAmB,EAAE,wBAAwB,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAA;CAC5E;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;IACpC,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAA;IACjC,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;CAC3C;AAiCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBACa,SAAU,SAAQ,UAAU;IACvC,OAAgB,MAAM,0BAAoB;IAE1C,wGAAwG;IAC5F,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAI;IAEnD,gEAAgE;IACpD,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAAI;IAEhD,6GAA6G;IAClD,cAAc,SAAK;IAE9E,2GAA2G;IAClD,YAAY,SAAK;IAE1E,gHAAgH;IACxE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAY;IAElF;;;;OAIG;IAC6B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,SAAS,CAAY;IAEjG;;;;OAIG;IAC6B,OAAO,EAAE,yBAAyB,EAAE,GAAG,SAAS,CAAY;IAEnF,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,SAAS,CAAe;IACzC,8EAA8E;IACrE,OAAO,CAAC,YAAY,CAAK;IAElC,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAEjC;IAED,kEAAkE;IAClE,OAAO,CAAC,UAAU,CAAwC;IAE1D,oDAAoD;IACpD,IAAI,WAAW,IAAI,MAAM,EAAE,CAE1B;IAED,iDAAiD;IACjD,IAAI,QAAQ,IAAI,MAAM,EAAE,CAEvB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,kFAAkF;IAClF,IAAI,sBAAsB,IAAI,yBAAyB,GAAG,SAAS,CAElE;IAEQ,iBAAiB;IAKjB,oBAAoB;cAKV,UAAU,CAAC,OAAO,EAAE,cAAc;cAclC,OAAO,CAAC,OAAO,EAAE,cAAc;IAYlD,6FAA6F;IAC7F,KAAK;IAcL,YAAY,CAAC,IAAI,EAAE,aAAa;IAKhC,cAAc,CAAC,IAAI,EAAE,aAAa;IAIlC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS;IAOtE,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAQlD,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAQ/C,YAAY;IAKZ;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAS5D;;;OAGG;IACH,OAAO,CAAC,WAAW;IAYnB,iHAAiH;IACjH,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,WAAW;IAkCnB,yGAAyG;IACzG,OAAO,CAAC,QAAQ;IAchB;;;OAGG;IACH,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,mBAAmB;IAI3B,kHAAkH;IAClH,OAAO,KAAK,gBAAgB,GAI3B;IAED,OAAO,CAAC,UAAU;IAUlB,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,OAAO;IAUN,MAAM;CAGhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,cAAc,EAAE,SAAS,CAAA;KAC1B;CACF"}
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../src/dashboard.ts"],"names":[],"mappings":"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"}