@ecopages/radiant-ui 0.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -0
- package/dist/components/ui/alert/alert.css +27 -0
- package/dist/components/ui/alert/alert.d.ts +4 -0
- package/dist/components/ui/alert/alert.script.d.ts +25 -0
- package/dist/components/ui/alert/index.d.ts +2 -0
- package/dist/components/ui/alert/index.js +2 -0
- package/dist/components/ui/alert/index.js.map +7 -0
- package/dist/components/ui/breadcrumb/breadcrumb.css +41 -0
- package/dist/components/ui/breadcrumb/breadcrumb.d.ts +59 -0
- package/dist/components/ui/breadcrumb/breadcrumb.script.d.ts +40 -0
- package/dist/components/ui/breadcrumb/index.d.ts +2 -0
- package/dist/components/ui/breadcrumb/index.js +2 -0
- package/dist/components/ui/breadcrumb/index.js.map +7 -0
- package/dist/components/ui/button/button.d.ts +37 -0
- package/dist/components/ui/button/index.d.ts +1 -0
- package/dist/components/ui/button/index.js +2 -0
- package/dist/components/ui/button/index.js.map +7 -0
- package/dist/components/ui/carousel/carousel.css +170 -0
- package/dist/components/ui/carousel/carousel.d.ts +39 -0
- package/dist/components/ui/carousel/carousel.script.d.ts +113 -0
- package/dist/components/ui/carousel/index.d.ts +2 -0
- package/dist/components/ui/carousel/index.js +2 -0
- package/dist/components/ui/carousel/index.js.map +7 -0
- package/dist/components/ui/checkbox/checkbox.css +55 -0
- package/dist/components/ui/checkbox/checkbox.d.ts +4 -0
- package/dist/components/ui/checkbox/checkbox.script.d.ts +58 -0
- package/dist/components/ui/checkbox/index.d.ts +2 -0
- package/dist/components/ui/checkbox/index.js +2 -0
- package/dist/components/ui/checkbox/index.js.map +7 -0
- package/dist/components/ui/combobox/combobox.css +65 -0
- package/dist/components/ui/combobox/combobox.d.ts +53 -0
- package/dist/components/ui/combobox/combobox.script.d.ts +89 -0
- package/dist/components/ui/combobox/index.d.ts +2 -0
- package/dist/components/ui/combobox/index.js +2 -0
- package/dist/components/ui/combobox/index.js.map +7 -0
- package/dist/components/ui/dialog/dialog-registry.d.ts +34 -0
- package/dist/components/ui/dialog/dialog-registry.test.d.ts +1 -0
- package/dist/components/ui/dialog/dialog-types.d.ts +55 -0
- package/dist/components/ui/dialog/dialog.css +53 -0
- package/dist/components/ui/dialog/dialog.d.ts +36 -0
- package/dist/components/ui/dialog/dialog.script.d.ts +61 -0
- package/dist/components/ui/dialog/index.d.ts +4 -0
- package/dist/components/ui/dialog/index.js +2 -0
- package/dist/components/ui/dialog/index.js.map +7 -0
- package/dist/components/ui/disclosure/disclosure-group.script.d.ts +31 -0
- package/dist/components/ui/disclosure/disclosure.css +105 -0
- package/dist/components/ui/disclosure/disclosure.d.ts +35 -0
- package/dist/components/ui/disclosure/disclosure.script.d.ts +38 -0
- package/dist/components/ui/disclosure/index.d.ts +3 -0
- package/dist/components/ui/disclosure/index.js +2 -0
- package/dist/components/ui/disclosure/index.js.map +7 -0
- package/dist/components/ui/feed/feed.css +14 -0
- package/dist/components/ui/feed/feed.d.ts +12 -0
- package/dist/components/ui/feed/feed.script.d.ts +22 -0
- package/dist/components/ui/feed/index.d.ts +2 -0
- package/dist/components/ui/feed/index.js +2 -0
- package/dist/components/ui/feed/index.js.map +7 -0
- package/dist/components/ui/field/field-context.d.ts +20 -0
- package/dist/components/ui/field/field-description.d.ts +8 -0
- package/dist/components/ui/field/field-error.d.ts +9 -0
- package/dist/components/ui/field/field-ssr-hydration.test.d.ts +1 -0
- package/dist/components/ui/field/field.css +26 -0
- package/dist/components/ui/field/field.d.ts +4 -0
- package/dist/components/ui/field/field.script.d.ts +68 -0
- package/dist/components/ui/field/index.d.ts +5 -0
- package/dist/components/ui/field/index.js +2 -0
- package/dist/components/ui/field/index.js.map +7 -0
- package/dist/components/ui/form/control-protocol.d.ts +19 -0
- package/dist/components/ui/form/form-context.d.ts +27 -0
- package/dist/components/ui/form/form-field.test.d.ts +3 -0
- package/dist/components/ui/form/form-store.d.ts +53 -0
- package/dist/components/ui/form/form-store.test.d.ts +1 -0
- package/dist/components/ui/form/form.css +12 -0
- package/dist/components/ui/form/form.d.ts +5 -0
- package/dist/components/ui/form/form.script.d.ts +67 -0
- package/dist/components/ui/form/index.d.ts +7 -0
- package/dist/components/ui/form/index.js +2 -0
- package/dist/components/ui/form/index.js.map +7 -0
- package/dist/components/ui/form/resolvers.d.ts +3 -0
- package/dist/components/ui/form/types.d.ts +72 -0
- package/dist/components/ui/grid/grid.css +47 -0
- package/dist/components/ui/grid/grid.d.ts +7 -0
- package/dist/components/ui/grid/grid.script.d.ts +26 -0
- package/dist/components/ui/grid/index.d.ts +2 -0
- package/dist/components/ui/grid/index.js +2 -0
- package/dist/components/ui/grid/index.js.map +7 -0
- package/dist/components/ui/input/index.d.ts +1 -0
- package/dist/components/ui/input/index.js +2 -0
- package/dist/components/ui/input/index.js.map +7 -0
- package/dist/components/ui/input/input.css +32 -0
- package/dist/components/ui/input/input.d.ts +23 -0
- package/dist/components/ui/label/index.d.ts +1 -0
- package/dist/components/ui/label/index.js +2 -0
- package/dist/components/ui/label/index.js.map +7 -0
- package/dist/components/ui/label/label.css +8 -0
- package/dist/components/ui/label/label.d.ts +9 -0
- package/dist/components/ui/listbox/index.d.ts +2 -0
- package/dist/components/ui/listbox/index.js +2 -0
- package/dist/components/ui/listbox/index.js.map +7 -0
- package/dist/components/ui/listbox/listbox.css +23 -0
- package/dist/components/ui/listbox/listbox.d.ts +12 -0
- package/dist/components/ui/listbox/listbox.script.d.ts +40 -0
- package/dist/components/ui/menu-button/index.d.ts +2 -0
- package/dist/components/ui/menu-button/index.js +2 -0
- package/dist/components/ui/menu-button/index.js.map +7 -0
- package/dist/components/ui/menu-button/menu-button.css +43 -0
- package/dist/components/ui/menu-button/menu-button.d.ts +13 -0
- package/dist/components/ui/menu-button/menu-button.script.d.ts +64 -0
- package/dist/components/ui/menubar/index.d.ts +2 -0
- package/dist/components/ui/menubar/index.js +2 -0
- package/dist/components/ui/menubar/index.js.map +7 -0
- package/dist/components/ui/menubar/menubar.css +45 -0
- package/dist/components/ui/menubar/menubar.d.ts +16 -0
- package/dist/components/ui/menubar/menubar.script.d.ts +52 -0
- package/dist/components/ui/meter/index.d.ts +2 -0
- package/dist/components/ui/meter/index.js +2 -0
- package/dist/components/ui/meter/index.js.map +7 -0
- package/dist/components/ui/meter/meter.css +17 -0
- package/dist/components/ui/meter/meter.d.ts +4 -0
- package/dist/components/ui/meter/meter.script.d.ts +33 -0
- package/dist/components/ui/navigation-menu/index.d.ts +2 -0
- package/dist/components/ui/navigation-menu/index.js +2 -0
- package/dist/components/ui/navigation-menu/index.js.map +7 -0
- package/dist/components/ui/navigation-menu/navigation-menu.css +90 -0
- package/dist/components/ui/navigation-menu/navigation-menu.d.ts +28 -0
- package/dist/components/ui/navigation-menu/navigation-menu.script.d.ts +49 -0
- package/dist/components/ui/radio-group/index.d.ts +2 -0
- package/dist/components/ui/radio-group/index.js +2 -0
- package/dist/components/ui/radio-group/index.js.map +7 -0
- package/dist/components/ui/radio-group/radio-group.css +44 -0
- package/dist/components/ui/radio-group/radio-group.d.ts +12 -0
- package/dist/components/ui/radio-group/radio-group.script.d.ts +52 -0
- package/dist/components/ui/sidebar/index.d.ts +3 -0
- package/dist/components/ui/sidebar/index.js +2 -0
- package/dist/components/ui/sidebar/index.js.map +7 -0
- package/dist/components/ui/sidebar/sidebar-trigger.script.d.ts +53 -0
- package/dist/components/ui/sidebar/sidebar.css +362 -0
- package/dist/components/ui/sidebar/sidebar.d.ts +141 -0
- package/dist/components/ui/sidebar/sidebar.script.d.ts +140 -0
- package/dist/components/ui/sidebar/sidebar.test.d.ts +1 -0
- package/dist/components/ui/slider/index.d.ts +2 -0
- package/dist/components/ui/slider/index.js +2 -0
- package/dist/components/ui/slider/index.js.map +7 -0
- package/dist/components/ui/slider/slider.css +51 -0
- package/dist/components/ui/slider/slider.d.ts +7 -0
- package/dist/components/ui/slider/slider.script.d.ts +102 -0
- package/dist/components/ui/spinbutton/index.d.ts +2 -0
- package/dist/components/ui/spinbutton/index.js +2 -0
- package/dist/components/ui/spinbutton/index.js.map +7 -0
- package/dist/components/ui/spinbutton/spinbutton.css +19 -0
- package/dist/components/ui/spinbutton/spinbutton.d.ts +4 -0
- package/dist/components/ui/spinbutton/spinbutton.script.d.ts +64 -0
- package/dist/components/ui/switch/index.d.ts +2 -0
- package/dist/components/ui/switch/index.js +2 -0
- package/dist/components/ui/switch/index.js.map +7 -0
- package/dist/components/ui/switch/switch.css +47 -0
- package/dist/components/ui/switch/switch.d.ts +4 -0
- package/dist/components/ui/switch/switch.script.d.ts +51 -0
- package/dist/components/ui/tabs/index.d.ts +2 -0
- package/dist/components/ui/tabs/index.js +2 -0
- package/dist/components/ui/tabs/index.js.map +7 -0
- package/dist/components/ui/tabs/tabs.css +28 -0
- package/dist/components/ui/tabs/tabs.d.ts +12 -0
- package/dist/components/ui/tabs/tabs.script.d.ts +54 -0
- package/dist/components/ui/textarea/index.d.ts +1 -0
- package/dist/components/ui/textarea/index.js +2 -0
- package/dist/components/ui/textarea/index.js.map +7 -0
- package/dist/components/ui/textarea/textarea.css +33 -0
- package/dist/components/ui/textarea/textarea.d.ts +23 -0
- package/dist/components/ui/toast/index.d.ts +5 -0
- package/dist/components/ui/toast/index.js +2 -0
- package/dist/components/ui/toast/index.js.map +7 -0
- package/dist/components/ui/toast/toast-api.d.ts +29 -0
- package/dist/components/ui/toast/toast-context.d.ts +59 -0
- package/dist/components/ui/toast/toast-state.d.ts +25 -0
- package/dist/components/ui/toast/toast.css +315 -0
- package/dist/components/ui/toast/toast.d.ts +8 -0
- package/dist/components/ui/toast/toast.script.d.ts +91 -0
- package/dist/components/ui/toast/toast.test.d.ts +2 -0
- package/dist/components/ui/toast/toaster.script.d.ts +79 -0
- package/dist/components/ui/toolbar/index.d.ts +2 -0
- package/dist/components/ui/toolbar/index.js +2 -0
- package/dist/components/ui/toolbar/index.js.map +7 -0
- package/dist/components/ui/toolbar/toolbar.css +16 -0
- package/dist/components/ui/toolbar/toolbar.d.ts +4 -0
- package/dist/components/ui/toolbar/toolbar.script.d.ts +30 -0
- package/dist/components/ui/tooltip/index.d.ts +2 -0
- package/dist/components/ui/tooltip/index.js +2 -0
- package/dist/components/ui/tooltip/index.js.map +7 -0
- package/dist/components/ui/tooltip/tooltip.css +25 -0
- package/dist/components/ui/tooltip/tooltip.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip.script.d.ts +70 -0
- package/dist/components/ui/tree/index.d.ts +2 -0
- package/dist/components/ui/tree/index.js +2 -0
- package/dist/components/ui/tree/index.js.map +7 -0
- package/dist/components/ui/tree/tree.css +54 -0
- package/dist/components/ui/tree/tree.d.ts +13 -0
- package/dist/components/ui/tree/tree.script.d.ts +45 -0
- package/dist/components/ui/treegrid/index.d.ts +2 -0
- package/dist/components/ui/treegrid/index.js +2 -0
- package/dist/components/ui/treegrid/index.js.map +7 -0
- package/dist/components/ui/treegrid/treegrid.css +77 -0
- package/dist/components/ui/treegrid/treegrid.d.ts +14 -0
- package/dist/components/ui/treegrid/treegrid.script.d.ts +49 -0
- package/dist/components/ui/window-splitter/index.d.ts +2 -0
- package/dist/components/ui/window-splitter/index.js +2 -0
- package/dist/components/ui/window-splitter/index.js.map +7 -0
- package/dist/components/ui/window-splitter/window-splitter.css +35 -0
- package/dist/components/ui/window-splitter/window-splitter.d.ts +8 -0
- package/dist/components/ui/window-splitter/window-splitter.script.d.ts +49 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +7 -0
- package/dist/lib/focusable-elements.d.ts +2 -0
- package/dist/lib/radiant-view.d.ts +17 -0
- package/dist/lib/roving-tabindex.d.ts +27 -0
- package/dist/styles/components/button.css +115 -0
- package/dist/styles/radiant-ui-core.css +7 -0
- package/dist/styles/radiant-ui.css +10 -0
- package/dist/styles/styles.css +36 -0
- package/dist/styles/tailwind.css +41 -0
- package/dist/styles/themes/aurora.css +19 -0
- package/dist/styles/themes/default-compact-soft.css +19 -0
- package/dist/styles/themes/default.css +2 -0
- package/dist/styles/themes/glacier.css +19 -0
- package/dist/styles/tokens/colors/aurora.css +73 -0
- package/dist/styles/tokens/colors/basalt.css +36 -0
- package/dist/styles/tokens/colors/glacier.css +45 -0
- package/dist/styles/tokens/colors/palettes.css +3 -0
- package/dist/styles/tokens/elevation/default.css +22 -0
- package/dist/styles/tokens/elevation/flat.css +22 -0
- package/dist/styles/tokens/motion/default.css +19 -0
- package/dist/styles/tokens/motion/snappy.css +19 -0
- package/dist/styles/tokens/presets/colors/aurora.css +126 -0
- package/dist/styles/tokens/presets/colors/basalt.css +126 -0
- package/dist/styles/tokens/presets/colors/ember.css +134 -0
- package/dist/styles/tokens/presets/colors/glacier.css +130 -0
- package/dist/styles/tokens/presets/colors/index.css +4 -0
- package/dist/styles/tokens/presets/radius.css +45 -0
- package/dist/styles/tokens/presets/spacing.css +57 -0
- package/dist/styles/tokens/radius/default.css +34 -0
- package/dist/styles/tokens/radius/edgy.css +35 -0
- package/dist/styles/tokens/radius/sharp.css +2 -0
- package/dist/styles/tokens/radius/soft.css +34 -0
- package/dist/styles/tokens/semantic.css +80 -0
- package/dist/styles/tokens/spacing/compact.css +23 -0
- package/dist/styles/tokens/spacing/default.css +23 -0
- package/dist/styles/tokens/spacing/scale-bridge.css +17 -0
- package/dist/styles/tokens/spacing/wide.css +23 -0
- package/dist/styles/tokens/system.css +36 -0
- package/dist/styles/tokens/typography/default.css +37 -0
- package/dist/styles/utilities/sheen.css +7 -0
- package/dist/types.d.ts +14 -0
- package/package.json +371 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{RadiantElement as E,customElement as v,event as b,onEvent as m,onUpdated as A,prop as h}from"@ecopages/radiant";function p(n,e){n.forEach((t,r)=>{t.tabIndex=r===e?0:-1})}function f(n,e){if(!n.length)return null;let t=Math.max(0,Math.min(n.length-1,e));return p(n,t),n[t]?.focus(),n[t]??null}var u=@v("rui-treegrid")class extends E{@h({type:String,defaultValue:""})label;@h({type:String,reflect:!0,defaultValue:""})value;@b({name:"rui-change",bubbles:!0,composed:!0})changeEvent;resolvedAriaLabel=this.$.label.map(e=>e||void 0);getDataRows(){return Array.from(this.querySelectorAll('[role="row"][data-row-id]'))}getVisibleRows(){return this.getDataRows().filter(e=>{let t=e.parentElement;for(;t&&t!==this;){if(t.getAttribute("role")==="rowgroup"&&t.hidden)return!1;t=t.parentElement}return!0})}getRowCells(e){return Array.from(e.querySelectorAll(':scope > [role="gridcell"]'))}getVisibleCells(){return this.getVisibleRows().flatMap(e=>this.getRowCells(e))}getParentRow(e){let t=e.parentElement;if(!t||t.getAttribute("role")!=="rowgroup")return null;let r=t.previousElementSibling;return r?.getAttribute("role")==="row"?r:null}syncExpanded(){for(let e of this.getDataRows()){if(!e.hasAttribute("aria-expanded"))continue;let t=e.nextElementSibling;t?.getAttribute("role")==="rowgroup"&&(t.hidden=e.getAttribute("aria-expanded")==="false")}}syncSelection(){let e=this.getVisibleCells(),t=0;for(let r of this.getDataRows()){let o=r.getAttribute("data-row-id")??"",s=!!this.value&&o===this.value;for(let a of this.getRowCells(r))if(a.setAttribute("aria-selected",String(s)),s){let l=e.indexOf(a);l>=0&&(t=l)}}e.length>0&&p(e,t)}connectedCallback(){super.connectedCallback(),queueMicrotask(()=>{this.syncExpanded(),this.syncSelection()})}@A("value")onValueUpdated(){this.syncSelection()}setExpanded(e,t){e.setAttribute("aria-expanded",String(t));let r=e.nextElementSibling;r?.getAttribute("role")==="rowgroup"&&(r.hidden=!t)}activateCell(e){let t=e.closest('[role="row"][data-row-id]');if(!t)return;let r=t.getAttribute("data-row-id")??"",o=this.getRowCells(t).indexOf(e);this.value=r,this.syncSelection(),this.changeEvent.emit({rowId:r,columnIndex:o}),e.focus()}focusCell(e,t){if(this.getVisibleRows().indexOf(e)<0)return;let s=this.getVisibleCells(),a=this.getRowCells(e),l=a[Math.min(Math.max(0,t),a.length-1)],d=s.indexOf(l);d>=0&&f(s,d)}@m({selector:'[role="gridcell"]',type:"click"})onCellClick(e){let t=e.target.closest('[role="gridcell"]');if(!t||!this.contains(t))return;let r=t.closest('[role="row"][data-row-id]');r&&this.getRowCells(r).indexOf(t)===0&&r.hasAttribute("aria-expanded")&&this.setExpanded(r,r.getAttribute("aria-expanded")!=="true"),this.activateCell(t)}@m({selector:'[role="gridcell"]',type:"keydown"})onCellKeydown(e){let t=e.target.closest('[role="gridcell"]'),r=t?.closest('[role="row"][data-row-id]');if(!t||!r)return;let o=this.getVisibleRows(),s=o.indexOf(r),a=this.getRowCells(r),l=a.indexOf(t),d=l===0,c=r.hasAttribute("aria-expanded"),g=r.getAttribute("aria-expanded")==="true";switch(e.key){case"ArrowRight":{if(e.preventDefault(),d&&c&&!g){this.setExpanded(r,!0),this.syncSelection();return}l<a.length-1&&this.focusCell(r,l+1);return}case"ArrowLeft":{if(e.preventDefault(),d&&c&&g){this.setExpanded(r,!1),this.syncSelection();return}if(l>0){this.focusCell(r,l-1);return}let i=this.getParentRow(r);i&&this.focusCell(i,0);return}case"ArrowDown":{e.preventDefault();let i=o[Math.min(o.length-1,s+1)];i&&i!==r&&this.focusCell(i,l);return}case"ArrowUp":{e.preventDefault();let i=o[Math.max(0,s-1)];i&&i!==r&&this.focusCell(i,l);return}case"Home":{e.preventDefault(),this.focusCell(r,0);return}case"End":{e.preventDefault(),this.focusCell(r,a.length-1);return}case"*":{e.preventDefault();for(let i of this.getDataRows())i.hasAttribute("aria-expanded")&&this.setExpanded(i,!0);this.syncSelection();return}case"Enter":{if(e.preventDefault(),d&&c){this.setExpanded(r,!g),this.syncSelection();return}this.activateCell(t);return}case" ":{e.preventDefault(),this.activateCell(t);return}default:return}}render(){return React.createElement("div",{class:"rui-treegrid",role:"treegrid","aria-label":this.resolvedAriaLabel},React.createElement("slot",null))}};var C=Symbol.for("@ecopages/storybook-radiant.viewElement"),R=Symbol.for("@ecopages/storybook-radiant.scriptModule"),w=Symbol.for("@ecopages/storybook-radiant.scriptExport");function M(n,e){n[C]=e;let t=e[R];t&&(n[R]=t,n[w]=e[w]??e.name)}function x(n,e){let t=(r=>e(r));return M(t,n),t}import"./treegrid.css";var T=({rows:n})=>React.createElement(React.Fragment,null,n.map(e=>React.createElement(React.Fragment,null,React.createElement("div",{class:"rui-treegrid__row",role:"row","data-row-id":e.id,"aria-expanded":e.children?.length?e.expanded??!1:void 0},e.cells.map((t,r)=>React.createElement("div",{class:"rui-treegrid__cell",role:"gridcell",tabindex:-1,"data-col":r,"aria-selected":"false"},t))),e.children?.length?React.createElement("div",{class:"rui-treegrid__group",role:"rowgroup",hidden:!(e.expanded??!1)},React.createElement(T,{rows:e.children})):null))),y=x(u,({slot:n,label:e,value:t,columns:r,rows:o})=>React.createElement("rui-treegrid",{slot:n,label:e,value:t},React.createElement("div",{class:"rui-treegrid__row rui-treegrid__row--header",role:"row"},r.map(s=>React.createElement("div",{class:"rui-treegrid__cell rui-treegrid__cell--header",role:"columnheader"},s))),React.createElement(T,{rows:o})));export{y as RuiTreegrid,u as RuiTreegridElement};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/components/ui/treegrid/treegrid.script.tsx", "../../../../src/lib/roving-tabindex.ts", "../../../../src/lib/radiant-view.ts", "../../../../src/components/ui/treegrid/treegrid.tsx"],
|
|
4
|
+
"sourcesContent": ["import { RadiantElement, customElement, event, onEvent, onUpdated, prop } from '@ecopages/radiant';\nimport type { EventEmitter } from '@ecopages/radiant/tools/event-emitter';\nimport { applyRovingTabindex, focusRovingItem } from '../../../lib/roving-tabindex';\n\nexport type RuiTreegridProps = {\n\tlabel?: string;\n\t/** Selected row `data-row-id`. */\n\tvalue?: string;\n};\n\nexport type RuiTreegridChangeDetail = {\n\trowId: string;\n\tcolumnIndex: number;\n};\n\ntype RuiTreegridBindings = {\n\tlabel: string;\n};\n\n/**\n * `<rui-treegrid>` \u2014 a hierarchical grid navigated with arrow keys.\n *\n * Implements a read-only APG Treegrid: rows may expand/collapse to reveal child\n * rows, and `role=\"gridcell\"` descendants are focused with roving tabindex.\n *\n * Expand/collapse with ArrowRight/ArrowLeft only from the first cell of a row\n * (APG cell-only focus). Enter or click on that cell toggles expansion; Space selects.\n *\n * @see https://www.w3.org/WAI/ARIA/apg/patterns/treegrid/\n * @element rui-treegrid\n * @fires rui-change\n */\n@customElement('rui-treegrid')\nexport class RuiTreegrid extends RadiantElement<RuiTreegridBindings> {\n\t@prop({ type: String, defaultValue: '' }) label: string;\n\t@prop({ type: String, reflect: true, defaultValue: '' }) value: string;\n\n\t@event({ name: 'rui-change', bubbles: true, composed: true })\n\tchangeEvent: EventEmitter<RuiTreegridChangeDetail>;\n\n\tprivate readonly resolvedAriaLabel = this.$.label.map((label) => label || undefined);\n\n\tprivate getDataRows(): HTMLElement[] {\n\t\treturn Array.from(this.querySelectorAll<HTMLElement>('[role=\"row\"][data-row-id]'));\n\t}\n\n\tprivate getVisibleRows(): HTMLElement[] {\n\t\treturn this.getDataRows().filter((row) => {\n\t\t\tlet parent = row.parentElement;\n\t\t\twhile (parent && parent !== this) {\n\t\t\t\tif (parent.getAttribute('role') === 'rowgroup' && parent.hidden) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tparent = parent.parentElement;\n\t\t\t}\n\t\t\treturn true;\n\t\t});\n\t}\n\n\tprivate getRowCells(row: HTMLElement): HTMLElement[] {\n\t\treturn Array.from(row.querySelectorAll<HTMLElement>(':scope > [role=\"gridcell\"]'));\n\t}\n\n\tprivate getVisibleCells(): HTMLElement[] {\n\t\treturn this.getVisibleRows().flatMap((row) => this.getRowCells(row));\n\t}\n\n\tprivate getParentRow(row: HTMLElement): HTMLElement | null {\n\t\tconst group = row.parentElement;\n\t\tif (!group || group.getAttribute('role') !== 'rowgroup') {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst parent = group.previousElementSibling as HTMLElement | null;\n\t\treturn parent?.getAttribute('role') === 'row' ? parent : null;\n\t}\n\n\tprivate syncExpanded(): void {\n\t\tfor (const row of this.getDataRows()) {\n\t\t\tif (!row.hasAttribute('aria-expanded')) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst group = row.nextElementSibling as HTMLElement | null;\n\t\t\tif (group?.getAttribute('role') === 'rowgroup') {\n\t\t\t\tgroup.hidden = row.getAttribute('aria-expanded') === 'false';\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate syncSelection(): void {\n\t\tconst cells = this.getVisibleCells();\n\t\tlet activeIndex = 0;\n\n\t\tfor (const row of this.getDataRows()) {\n\t\t\tconst rowId = row.getAttribute('data-row-id') ?? '';\n\t\t\tconst selected = Boolean(this.value) && rowId === this.value;\n\t\t\tfor (const cell of this.getRowCells(row)) {\n\t\t\t\tcell.setAttribute('aria-selected', String(selected));\n\t\t\t\tif (selected) {\n\t\t\t\t\tconst index = cells.indexOf(cell);\n\t\t\t\t\tif (index >= 0) {\n\t\t\t\t\t\tactiveIndex = index;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (cells.length > 0) {\n\t\t\tapplyRovingTabindex(cells, activeIndex);\n\t\t}\n\t}\n\n\toverride connectedCallback(): void {\n\t\tsuper.connectedCallback();\n\t\tqueueMicrotask(() => {\n\t\t\tthis.syncExpanded();\n\t\t\tthis.syncSelection();\n\t\t});\n\t}\n\n\t@onUpdated('value')\n\tonValueUpdated(): void {\n\t\tthis.syncSelection();\n\t}\n\n\tprivate setExpanded(row: HTMLElement, expanded: boolean): void {\n\t\trow.setAttribute('aria-expanded', String(expanded));\n\t\tconst group = row.nextElementSibling as HTMLElement | null;\n\t\tif (group?.getAttribute('role') === 'rowgroup') {\n\t\t\tgroup.hidden = !expanded;\n\t\t}\n\t}\n\n\tprivate activateCell(cell: HTMLElement): void {\n\t\tconst row = cell.closest<HTMLElement>('[role=\"row\"][data-row-id]');\n\t\tif (!row) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rowId = row.getAttribute('data-row-id') ?? '';\n\t\tconst columnIndex = this.getRowCells(row).indexOf(cell);\n\t\tthis.value = rowId;\n\t\tthis.syncSelection();\n\t\tthis.changeEvent.emit({ rowId, columnIndex });\n\t\tcell.focus();\n\t}\n\n\tprivate focusCell(row: HTMLElement, columnIndex: number): void {\n\t\tconst rows = this.getVisibleRows();\n\t\tconst rowIndex = rows.indexOf(row);\n\t\tif (rowIndex < 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst cells = this.getVisibleCells();\n\t\tconst rowCells = this.getRowCells(row);\n\t\tconst target = rowCells[Math.min(Math.max(0, columnIndex), rowCells.length - 1)];\n\t\tconst nextIndex = cells.indexOf(target);\n\t\tif (nextIndex >= 0) {\n\t\t\tfocusRovingItem(cells, nextIndex);\n\t\t}\n\t}\n\n\t@onEvent({ selector: '[role=\"gridcell\"]', type: 'click' })\n\tonCellClick(event: Event): void {\n\t\tconst cell = (event.target as HTMLElement).closest<HTMLElement>('[role=\"gridcell\"]');\n\t\tif (!cell || !this.contains(cell)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst row = cell.closest<HTMLElement>('[role=\"row\"][data-row-id]');\n\t\tif (row) {\n\t\t\tconst isFirstCell = this.getRowCells(row).indexOf(cell) === 0;\n\t\t\tif (isFirstCell && row.hasAttribute('aria-expanded')) {\n\t\t\t\tthis.setExpanded(row, row.getAttribute('aria-expanded') !== 'true');\n\t\t\t}\n\t\t}\n\n\t\tthis.activateCell(cell);\n\t}\n\n\t@onEvent({ selector: '[role=\"gridcell\"]', type: 'keydown' })\n\tonCellKeydown(event: KeyboardEvent): void {\n\t\tconst cell = (event.target as HTMLElement).closest<HTMLElement>('[role=\"gridcell\"]');\n\t\tconst row = cell?.closest<HTMLElement>('[role=\"row\"][data-row-id]');\n\t\tif (!cell || !row) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst visibleRows = this.getVisibleRows();\n\t\tconst rowIndex = visibleRows.indexOf(row);\n\t\tconst rowCells = this.getRowCells(row);\n\t\tconst colIndex = rowCells.indexOf(cell);\n\t\tconst isFirstCell = colIndex === 0;\n\t\tconst isExpandable = row.hasAttribute('aria-expanded');\n\t\tconst isExpanded = row.getAttribute('aria-expanded') === 'true';\n\n\t\tswitch (event.key) {\n\t\t\tcase 'ArrowRight': {\n\t\t\t\tevent.preventDefault();\n\t\t\t\t// APG cell-only: expand only from the first cell of a collapsed parent.\n\t\t\t\tif (isFirstCell && isExpandable && !isExpanded) {\n\t\t\t\t\tthis.setExpanded(row, true);\n\t\t\t\t\tthis.syncSelection();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (colIndex < rowCells.length - 1) {\n\t\t\t\t\tthis.focusCell(row, colIndex + 1);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase 'ArrowLeft': {\n\t\t\t\tevent.preventDefault();\n\t\t\t\t// APG cell-only: collapse only from the first cell of an expanded parent.\n\t\t\t\tif (isFirstCell && isExpandable && isExpanded) {\n\t\t\t\t\tthis.setExpanded(row, false);\n\t\t\t\t\tthis.syncSelection();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (colIndex > 0) {\n\t\t\t\t\tthis.focusCell(row, colIndex - 1);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst parent = this.getParentRow(row);\n\t\t\t\tif (parent) {\n\t\t\t\t\tthis.focusCell(parent, 0);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase 'ArrowDown': {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tconst nextRow = visibleRows[Math.min(visibleRows.length - 1, rowIndex + 1)];\n\t\t\t\tif (nextRow && nextRow !== row) {\n\t\t\t\t\tthis.focusCell(nextRow, colIndex);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase 'ArrowUp': {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tconst prevRow = visibleRows[Math.max(0, rowIndex - 1)];\n\t\t\t\tif (prevRow && prevRow !== row) {\n\t\t\t\t\tthis.focusCell(prevRow, colIndex);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase 'Home': {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tthis.focusCell(row, 0);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase 'End': {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tthis.focusCell(row, rowCells.length - 1);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase '*': {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tfor (const sibling of this.getDataRows()) {\n\t\t\t\t\tif (sibling.hasAttribute('aria-expanded')) {\n\t\t\t\t\t\tthis.setExpanded(sibling, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis.syncSelection();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase 'Enter': {\n\t\t\t\tevent.preventDefault();\n\t\t\t\t// APG: Enter on the first cell of an expandable row toggles expansion.\n\t\t\t\tif (isFirstCell && isExpandable) {\n\t\t\t\t\tthis.setExpanded(row, !isExpanded);\n\t\t\t\t\tthis.syncSelection();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.activateCell(cell);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcase ' ': {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tthis.activateCell(cell);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\toverride render() {\n\t\treturn (\n\t\t\t<div class=\"rui-treegrid\" role=\"treegrid\" aria-label={this.resolvedAriaLabel}>\n\t\t\t\t<slot></slot>\n\t\t\t</div>\n\t\t);\n\t}\n}\n", "export type RovingOrientation = 'horizontal' | 'vertical';\n\nexport type RovingNavResult = { handled: false } | { handled: true; index: number; item: HTMLElement };\n\n/**\n * Apply the APG roving-tabindex pattern: one item is tabbable, the rest are `-1`.\n */\nexport function applyRovingTabindex(items: HTMLElement[], activeIndex: number): void {\n\titems.forEach((item, index) => {\n\t\titem.tabIndex = index === activeIndex ? 0 : -1;\n\t});\n}\n\n/**\n * Focus `items[index]` and update tabindexes. Returns the focused item, or null.\n */\nexport function focusRovingItem(items: HTMLElement[], index: number): HTMLElement | null {\n\tif (!items.length) return null;\n\tconst next = Math.max(0, Math.min(items.length - 1, index));\n\tapplyRovingTabindex(items, next);\n\titems[next]?.focus();\n\treturn items[next] ?? null;\n}\n\nfunction deltaForKey(key: string, orientation: RovingOrientation): 'prev' | 'next' | 'first' | 'last' | null {\n\tif (key === 'Home') return 'first';\n\tif (key === 'End') return 'last';\n\n\tif (orientation === 'horizontal') {\n\t\tif (key === 'ArrowRight') return 'next';\n\t\tif (key === 'ArrowLeft') return 'prev';\n\t\treturn null;\n\t}\n\n\tif (key === 'ArrowDown') return 'next';\n\tif (key === 'ArrowUp') return 'prev';\n\treturn null;\n}\n\n/**\n * Handle arrow / Home / End navigation for a flat roving-tabindex collection.\n * Does not activate the item \u2014 callers decide whether to select on move.\n */\nexport function navigateRovingTabindex(options: {\n\titems: HTMLElement[];\n\tcurrent: HTMLElement | null;\n\tkey: string;\n\torientation?: RovingOrientation;\n\twrap?: boolean;\n}): RovingNavResult {\n\tconst { items, current, key, orientation = 'horizontal', wrap = true } = options;\n\tif (!items.length || !current) return { handled: false };\n\n\tconst index = items.indexOf(current);\n\tif (index < 0) return { handled: false };\n\n\tconst delta = deltaForKey(key, orientation);\n\tif (!delta) return { handled: false };\n\n\tlet next = index;\n\tif (delta === 'first') next = 0;\n\telse if (delta === 'last') next = items.length - 1;\n\telse if (delta === 'next') next = wrap ? (index + 1) % items.length : Math.min(items.length - 1, index + 1);\n\telse next = wrap ? (index - 1 + items.length) % items.length : Math.max(0, index - 1);\n\n\tconst item = focusRovingItem(items, next);\n\tif (!item) return { handled: false };\n\treturn { handled: true, index: next, item };\n}\n", "import type { JsxRenderable } from '@ecopages/jsx';\n\nconst RADIANT_VIEW_ELEMENT = Symbol.for('@ecopages/storybook-radiant.viewElement');\nconst RADIANT_SCRIPT_MODULE = Symbol.for('@ecopages/storybook-radiant.scriptModule');\nconst RADIANT_SCRIPT_EXPORT = Symbol.for('@ecopages/storybook-radiant.scriptExport');\n\nexport type RadiantViewComponent<TArgs = unknown> = ((args: TArgs) => JsxRenderable) & {\n\t[RADIANT_VIEW_ELEMENT]?: CustomElementConstructor;\n\t[RADIANT_SCRIPT_MODULE]?: string;\n\t[RADIANT_SCRIPT_EXPORT]?: string;\n};\n\nfunction linkViewToElement<TArgs>(\n\tview: RadiantViewComponent<TArgs>,\n\telement: CustomElementConstructor & {\n\t\t[RADIANT_SCRIPT_MODULE]?: string;\n\t\t[RADIANT_SCRIPT_EXPORT]?: string;\n\t},\n): void {\n\tview[RADIANT_VIEW_ELEMENT] = element;\n\n\tconst ssrModule = element[RADIANT_SCRIPT_MODULE];\n\tif (ssrModule) {\n\t\tview[RADIANT_SCRIPT_MODULE] = ssrModule;\n\t\tview[RADIANT_SCRIPT_EXPORT] = element[RADIANT_SCRIPT_EXPORT] ?? element.name;\n\t}\n}\n\n/** Link a JSX view export to its RadiantElement class (same symbols as the Storybook framework). */\nexport function defineRadiantView<TArgs>(\n\telement: CustomElementConstructor & {\n\t\t[RADIANT_SCRIPT_MODULE]?: string;\n\t\t[RADIANT_SCRIPT_EXPORT]?: string;\n\t},\n\trender: (args: TArgs) => JsxRenderable,\n): RadiantViewComponent<TArgs> {\n\tconst view = ((args: TArgs) => render(args)) as RadiantViewComponent<TArgs>;\n\tlinkViewToElement(view, element);\n\treturn view;\n}\n\n/** Re-copy SSR metadata from the linked element (e.g. after HMR). */\nexport function syncRadiantViewMetadata(view: RadiantViewComponent): void {\n\tconst element = view[RADIANT_VIEW_ELEMENT];\n\tif (element) {\n\t\tlinkViewToElement(view, element);\n\t}\n}\n", "import type { JsxRenderable } from '@ecopages/jsx';\nimport type { RadiantSlotProps } from '../../../types';\nimport { defineRadiantView } from '../../../lib/radiant-view';\nimport type { RuiTreegridProps } from './treegrid.script';\nimport { RuiTreegrid as RuiTreegridElement } from './treegrid.script';\nimport './treegrid.css';\n\nexport type RuiTreegridRow = {\n\tid: string;\n\tcells: JsxRenderable[];\n\tchildren?: RuiTreegridRow[];\n\texpanded?: boolean;\n};\n\nconst TreegridRows = ({ rows }: { rows: RuiTreegridRow[] }) => (\n\t<>\n\t\t{rows.map((row) => (\n\t\t\t<>\n\t\t\t\t<div\n\t\t\t\t\tclass=\"rui-treegrid__row\"\n\t\t\t\t\trole=\"row\"\n\t\t\t\t\tdata-row-id={row.id}\n\t\t\t\t\taria-expanded={row.children?.length ? (row.expanded ?? false) : undefined}\n\t\t\t\t>\n\t\t\t\t\t{row.cells.map((cell, index) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclass=\"rui-treegrid__cell\"\n\t\t\t\t\t\t\trole=\"gridcell\"\n\t\t\t\t\t\t\ttabindex={-1}\n\t\t\t\t\t\t\tdata-col={index}\n\t\t\t\t\t\t\taria-selected=\"false\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{cell}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{row.children?.length ? (\n\t\t\t\t\t<div class=\"rui-treegrid__group\" role=\"rowgroup\" hidden={!(row.expanded ?? false)}>\n\t\t\t\t\t\t<TreegridRows rows={row.children} />\n\t\t\t\t\t</div>\n\t\t\t\t) : null}\n\t\t\t</>\n\t\t))}\n\t</>\n);\n\nexport const RuiTreegrid = defineRadiantView(\n\tRuiTreegridElement,\n\t({\n\t\tslot,\n\t\tlabel,\n\t\tvalue,\n\t\tcolumns,\n\t\trows,\n\t}: RuiTreegridProps & RadiantSlotProps & { columns: JsxRenderable[]; rows: RuiTreegridRow[] }) => (\n\t\t<rui-treegrid slot={slot} label={label} value={value}>\n\t\t\t<div class=\"rui-treegrid__row rui-treegrid__row--header\" role=\"row\">\n\t\t\t\t{columns.map((column) => (\n\t\t\t\t\t<div class=\"rui-treegrid__cell rui-treegrid__cell--header\" role=\"columnheader\">\n\t\t\t\t\t\t{column}\n\t\t\t\t\t</div>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t\t<TreegridRows rows={rows} />\n\t\t</rui-treegrid>\n\t),\n);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["RadiantElement", "customElement", "event", "onEvent", "onUpdated", "prop", "applyRovingTabindex", "items", "activeIndex", "item", "index", "focusRovingItem", "next", "RuiTreegrid", "customElement", "RadiantElement", "prop", "event", "label", "row", "parent", "group", "cells", "activeIndex", "rowId", "selected", "cell", "index", "applyRovingTabindex", "onUpdated", "expanded", "columnIndex", "rowCells", "target", "nextIndex", "focusRovingItem", "onEvent", "visibleRows", "rowIndex", "colIndex", "isFirstCell", "isExpandable", "isExpanded", "nextRow", "prevRow", "sibling", "RADIANT_VIEW_ELEMENT", "RADIANT_SCRIPT_MODULE", "RADIANT_SCRIPT_EXPORT", "linkViewToElement", "view", "element", "ssrModule", "defineRadiantView", "render", "args", "TreegridRows", "rows", "row", "cell", "index", "RuiTreegrid", "defineRadiantView", "slot", "label", "value", "columns", "column"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
@reference '../../../styles/radiant-ui.css';
|
|
2
|
+
|
|
3
|
+
rui-treegrid {
|
|
4
|
+
@apply block;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
@layer components {
|
|
8
|
+
.rui-treegrid {
|
|
9
|
+
@apply w-full overflow-hidden rounded-container border border-border text-sm shadow-sm;
|
|
10
|
+
display: table;
|
|
11
|
+
border-collapse: separate;
|
|
12
|
+
border-spacing: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.rui-treegrid__row {
|
|
16
|
+
display: table-row;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.rui-treegrid__group {
|
|
20
|
+
display: table-row-group;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.rui-treegrid__row:not(.rui-treegrid__row--header):hover .rui-treegrid__cell {
|
|
24
|
+
@apply bg-surface/60;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.rui-treegrid__cell {
|
|
28
|
+
display: table-cell;
|
|
29
|
+
@apply border-b border-r border-border bg-background px-control-x py-2.5 align-middle text-on-background;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.rui-treegrid__row .rui-treegrid__cell:last-child {
|
|
33
|
+
@apply border-r-0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.rui-treegrid__row:last-child .rui-treegrid__cell {
|
|
37
|
+
@apply border-b-0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.rui-treegrid__cell--header {
|
|
41
|
+
@apply bg-surface font-semibold text-on-background;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.rui-treegrid__cell[aria-selected='true'] {
|
|
45
|
+
@apply bg-primary-container font-medium text-on-primary-container;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.rui-treegrid__cell:focus-visible {
|
|
49
|
+
@apply relative z-dropdown outline-none ring-2 ring-inset ring-focus-ring;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.rui-treegrid__group .rui-treegrid__cell:first-child {
|
|
53
|
+
@apply pl-8;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.rui-treegrid__group .rui-treegrid__group .rui-treegrid__cell:first-child {
|
|
57
|
+
@apply pl-12;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.rui-treegrid__row[aria-expanded='false'] .rui-treegrid__cell:first-child::before,
|
|
61
|
+
.rui-treegrid__row[aria-expanded='true'] .rui-treegrid__cell:first-child::before {
|
|
62
|
+
content: '';
|
|
63
|
+
display: inline-block;
|
|
64
|
+
width: 0;
|
|
65
|
+
height: 0;
|
|
66
|
+
margin-right: 0.5rem;
|
|
67
|
+
border-top: 4px solid transparent;
|
|
68
|
+
border-bottom: 4px solid transparent;
|
|
69
|
+
border-left: 6px solid currentColor;
|
|
70
|
+
vertical-align: middle;
|
|
71
|
+
transition: transform 150ms ease;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.rui-treegrid__row[aria-expanded='true'] .rui-treegrid__cell:first-child::before {
|
|
75
|
+
transform: rotate(90deg);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { JsxRenderable } from '@ecopages/jsx';
|
|
2
|
+
import type { RadiantSlotProps } from '../../../types';
|
|
3
|
+
import type { RuiTreegridProps } from './treegrid.script';
|
|
4
|
+
import './treegrid.css';
|
|
5
|
+
export type RuiTreegridRow = {
|
|
6
|
+
id: string;
|
|
7
|
+
cells: JsxRenderable[];
|
|
8
|
+
children?: RuiTreegridRow[];
|
|
9
|
+
expanded?: boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare const RuiTreegrid: import("../../../lib/radiant-view").RadiantViewComponent<RuiTreegridProps & RadiantSlotProps & {
|
|
12
|
+
columns: JsxRenderable[];
|
|
13
|
+
rows: RuiTreegridRow[];
|
|
14
|
+
}>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { RadiantElement } from '@ecopages/radiant';
|
|
2
|
+
import type { EventEmitter } from '@ecopages/radiant/tools/event-emitter';
|
|
3
|
+
export type RuiTreegridProps = {
|
|
4
|
+
label?: string;
|
|
5
|
+
/** Selected row `data-row-id`. */
|
|
6
|
+
value?: string;
|
|
7
|
+
};
|
|
8
|
+
export type RuiTreegridChangeDetail = {
|
|
9
|
+
rowId: string;
|
|
10
|
+
columnIndex: number;
|
|
11
|
+
};
|
|
12
|
+
type RuiTreegridBindings = {
|
|
13
|
+
label: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* `<rui-treegrid>` — a hierarchical grid navigated with arrow keys.
|
|
17
|
+
*
|
|
18
|
+
* Implements a read-only APG Treegrid: rows may expand/collapse to reveal child
|
|
19
|
+
* rows, and `role="gridcell"` descendants are focused with roving tabindex.
|
|
20
|
+
*
|
|
21
|
+
* Expand/collapse with ArrowRight/ArrowLeft only from the first cell of a row
|
|
22
|
+
* (APG cell-only focus). Enter or click on that cell toggles expansion; Space selects.
|
|
23
|
+
*
|
|
24
|
+
* @see https://www.w3.org/WAI/ARIA/apg/patterns/treegrid/
|
|
25
|
+
* @element rui-treegrid
|
|
26
|
+
* @fires rui-change
|
|
27
|
+
*/
|
|
28
|
+
export declare class RuiTreegrid extends RadiantElement<RuiTreegridBindings> {
|
|
29
|
+
label: string;
|
|
30
|
+
value: string;
|
|
31
|
+
changeEvent: EventEmitter<RuiTreegridChangeDetail>;
|
|
32
|
+
private readonly resolvedAriaLabel;
|
|
33
|
+
private getDataRows;
|
|
34
|
+
private getVisibleRows;
|
|
35
|
+
private getRowCells;
|
|
36
|
+
private getVisibleCells;
|
|
37
|
+
private getParentRow;
|
|
38
|
+
private syncExpanded;
|
|
39
|
+
private syncSelection;
|
|
40
|
+
connectedCallback(): void;
|
|
41
|
+
onValueUpdated(): void;
|
|
42
|
+
private setExpanded;
|
|
43
|
+
private activateCell;
|
|
44
|
+
private focusCell;
|
|
45
|
+
onCellClick(event: Event): void;
|
|
46
|
+
onCellKeydown(event: KeyboardEvent): void;
|
|
47
|
+
render(): import("@ecopages/jsx").JsxRenderable;
|
|
48
|
+
}
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{RadiantElement as c,bound as a,customElement as h,event as g,onEvent as s,onUpdated as w,prop as n,query as l}from"@ecopages/radiant";var o=@h("rui-window-splitter")class extends c{@n({type:Number,reflect:!0,defaultValue:50})value;@n({type:String,defaultValue:"horizontal"})orientation;@n({type:String,defaultValue:"Split view"})label;@l({ref:"primary"})primaryTarget;@l({ref:"separator"})separatorTarget;@g({name:"rui-splitter-change",bubbles:!0,composed:!0})changeEvent;resolvedAriaOrientation=this.$.orientation.map(e=>e!=="vertical"?"vertical":"horizontal");dragging=!1;connectedCallback(){super.connectedCallback(),queueMicrotask(()=>this.applySize())}disconnectedCallback(){document.removeEventListener("pointermove",this.onPointerMove),document.removeEventListener("pointerup",this.onPointerUp),super.disconnectedCallback()}@w(["value","orientation"])onPropsUpdated(){this.applySize()}applySize(){if(!this.primaryTarget)return;let e=`${Math.min(80,Math.max(20,this.value))}%`;this.orientation==="vertical"?(this.primaryTarget.style.height=e,this.primaryTarget.style.width=""):(this.primaryTarget.style.width=e,this.primaryTarget.style.height="")}@s({ref:"separator",type:"keydown"})onKeydown(e){let t=e.shiftKey?10:2,r=this.orientation!=="vertical";r&&e.key==="ArrowLeft"||!r&&e.key==="ArrowUp"?(e.preventDefault(),this.updateValue(Math.max(20,this.value-t))):r&&e.key==="ArrowRight"||!r&&e.key==="ArrowDown"?(e.preventDefault(),this.updateValue(Math.min(80,this.value+t))):e.key==="Home"?(e.preventDefault(),this.updateValue(20)):e.key==="End"&&(e.preventDefault(),this.updateValue(80))}updateValue(e){e!==this.value&&(this.value=e,this.changeEvent.emit({value:e}))}@s({ref:"separator",type:"pointerdown"})onPointerDown(e){this.dragging=!0,this.separatorTarget.setPointerCapture(e.pointerId),document.addEventListener("pointermove",this.onPointerMove),document.addEventListener("pointerup",this.onPointerUp)}@a onPointerMove(e){if(!this.dragging)return;let t=this.getBoundingClientRect();this.orientation==="vertical"?this.updateValue(Math.min(80,Math.max(20,(e.clientY-t.top)/t.height*100))):this.updateValue(Math.min(80,Math.max(20,(e.clientX-t.left)/t.width*100)))}@a onPointerUp(){this.dragging=!1,document.removeEventListener("pointermove",this.onPointerMove),document.removeEventListener("pointerup",this.onPointerUp)}render(){let e=this.orientation!=="vertical";return React.createElement("div",{class:`rui-window-splitter rui-window-splitter--${e?"horizontal":"vertical"}`},React.createElement("div",{"data-ref":"primary",class:"rui-window-splitter__pane"},React.createElement("slot",{name:"primary"})),React.createElement("div",{"data-ref":"separator",class:"rui-window-splitter__separator",role:"separator",tabindex:0,"aria-orientation":this.resolvedAriaOrientation,"aria-valuenow":this.$.value,"aria-valuemin":20,"aria-valuemax":80,"aria-label":this.$.label}),React.createElement("div",{class:"rui-window-splitter__pane"},React.createElement("slot",{name:"secondary"})))}};var y=Symbol.for("@ecopages/storybook-radiant.viewElement"),p=Symbol.for("@ecopages/storybook-radiant.scriptModule"),d=Symbol.for("@ecopages/storybook-radiant.scriptExport");function R(i,e){i[y]=e;let t=e[p];t&&(i[p]=t,i[d]=e[d]??e.name)}function u(i,e){let t=(r=>e(r));return R(t,i),t}import"./window-splitter.css";var f=u(o,({slot:i,value:e,orientation:t,label:r,primary:m,secondary:v})=>React.createElement("rui-window-splitter",{slot:i,value:e,orientation:t,label:r},React.createElement("div",{slot:"primary"},m),React.createElement("div",{slot:"secondary"},v)));export{f as RuiWindowSplitter,o as RuiWindowSplitterElement};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/components/ui/window-splitter/window-splitter.script.tsx", "../../../../src/lib/radiant-view.ts", "../../../../src/components/ui/window-splitter/window-splitter.tsx"],
|
|
4
|
+
"sourcesContent": ["import { RadiantElement, bound, customElement, event, onEvent, onUpdated, prop, query } from '@ecopages/radiant';\nimport type { EventEmitter } from '@ecopages/radiant/tools/event-emitter';\n\nexport type RuiWindowSplitterProps = {\n\t/** Primary pane size as a percentage. Default: `50`. */\n\tvalue?: number;\n\t/** Orientation of the split. Default: `horizontal` (left/right panes). */\n\torientation?: 'horizontal' | 'vertical';\n\tlabel?: string;\n};\n\nexport type RuiWindowSplitterChangeDetail = { value: number };\n\ntype RuiWindowSplitterBindings = {\n\tvalue: number;\n\tlabel: string;\n\torientation: NonNullable<RuiWindowSplitterProps['orientation']>;\n};\n\n/**\n * `<rui-window-splitter>` \u2014 a movable separator between two panes.\n *\n * Implements the APG Window Splitter pattern with a focusable separator that\n * adjusts pane size via arrow keys and pointer drag. `value` and `orientation`\n * are reactive props.\n *\n * @see https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/\n * @element rui-window-splitter\n */\n@customElement('rui-window-splitter')\nexport class RuiWindowSplitter extends RadiantElement<RuiWindowSplitterBindings> {\n\t@prop({ type: Number, reflect: true, defaultValue: 50 }) value: number;\n\t@prop({ type: String, defaultValue: 'horizontal' }) orientation: NonNullable<RuiWindowSplitterProps['orientation']>;\n\t@prop({ type: String, defaultValue: 'Split view' }) label: string;\n\n\t@query({ ref: 'primary' }) primaryTarget: HTMLElement;\n\t@query({ ref: 'separator' }) separatorTarget: HTMLElement;\n\n\t@event({ name: 'rui-splitter-change', bubbles: true, composed: true })\n\tchangeEvent: EventEmitter<RuiWindowSplitterChangeDetail>;\n\n\t/** `class` stays a plain-read composition; only the derived aria-orientation string is bound. */\n\tprivate readonly resolvedAriaOrientation = this.$.orientation.map((orientation) =>\n\t\torientation !== 'vertical' ? 'vertical' : 'horizontal',\n\t);\n\n\tprivate dragging = false;\n\n\toverride connectedCallback(): void {\n\t\tsuper.connectedCallback();\n\t\tqueueMicrotask(() => this.applySize());\n\t}\n\n\toverride disconnectedCallback(): void {\n\t\tdocument.removeEventListener('pointermove', this.onPointerMove);\n\t\tdocument.removeEventListener('pointerup', this.onPointerUp);\n\t\tsuper.disconnectedCallback();\n\t}\n\n\t@onUpdated(['value', 'orientation'])\n\tonPropsUpdated(): void {\n\t\tthis.applySize();\n\t}\n\n\tprivate applySize(): void {\n\t\tif (!this.primaryTarget) return;\n\t\tconst size = `${Math.min(80, Math.max(20, this.value))}%`;\n\t\tif (this.orientation === 'vertical') {\n\t\t\tthis.primaryTarget.style.height = size;\n\t\t\tthis.primaryTarget.style.width = '';\n\t\t} else {\n\t\t\tthis.primaryTarget.style.width = size;\n\t\t\tthis.primaryTarget.style.height = '';\n\t\t}\n\t}\n\n\t@onEvent({ ref: 'separator', type: 'keydown' })\n\tonKeydown(event: KeyboardEvent): void {\n\t\tconst delta = event.shiftKey ? 10 : 2;\n\t\tconst horizontal = this.orientation !== 'vertical';\n\t\tif ((horizontal && event.key === 'ArrowLeft') || (!horizontal && event.key === 'ArrowUp')) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.updateValue(Math.max(20, this.value - delta));\n\t\t} else if ((horizontal && event.key === 'ArrowRight') || (!horizontal && event.key === 'ArrowDown')) {\n\t\t\tevent.preventDefault();\n\t\t\tthis.updateValue(Math.min(80, this.value + delta));\n\t\t} else if (event.key === 'Home') {\n\t\t\tevent.preventDefault();\n\t\t\tthis.updateValue(20);\n\t\t} else if (event.key === 'End') {\n\t\t\tevent.preventDefault();\n\t\t\tthis.updateValue(80);\n\t\t}\n\t}\n\n\tprivate updateValue(next: number): void {\n\t\tif (next === this.value) return;\n\t\tthis.value = next;\n\t\tthis.changeEvent.emit({ value: next });\n\t}\n\n\t@onEvent({ ref: 'separator', type: 'pointerdown' })\n\tonPointerDown(event: PointerEvent): void {\n\t\tthis.dragging = true;\n\t\tthis.separatorTarget.setPointerCapture(event.pointerId);\n\t\tdocument.addEventListener('pointermove', this.onPointerMove);\n\t\tdocument.addEventListener('pointerup', this.onPointerUp);\n\t}\n\n\t@bound\n\tonPointerMove(event: PointerEvent): void {\n\t\tif (!this.dragging) return;\n\t\tconst rect = this.getBoundingClientRect();\n\t\tif (this.orientation === 'vertical') {\n\t\t\tthis.updateValue(Math.min(80, Math.max(20, ((event.clientY - rect.top) / rect.height) * 100)));\n\t\t} else {\n\t\t\tthis.updateValue(Math.min(80, Math.max(20, ((event.clientX - rect.left) / rect.width) * 100)));\n\t\t}\n\t}\n\n\t@bound\n\tonPointerUp(): void {\n\t\tthis.dragging = false;\n\t\tdocument.removeEventListener('pointermove', this.onPointerMove);\n\t\tdocument.removeEventListener('pointerup', this.onPointerUp);\n\t}\n\n\toverride render() {\n\t\tconst horizontal = this.orientation !== 'vertical';\n\t\treturn (\n\t\t\t<div class={`rui-window-splitter rui-window-splitter--${horizontal ? 'horizontal' : 'vertical'}`}>\n\t\t\t\t<div data-ref=\"primary\" class=\"rui-window-splitter__pane\">\n\t\t\t\t\t<slot name=\"primary\"></slot>\n\t\t\t\t</div>\n\t\t\t\t<div\n\t\t\t\t\tdata-ref=\"separator\"\n\t\t\t\t\tclass=\"rui-window-splitter__separator\"\n\t\t\t\t\trole=\"separator\"\n\t\t\t\t\ttabindex={0}\n\t\t\t\t\taria-orientation={this.resolvedAriaOrientation}\n\t\t\t\t\taria-valuenow={this.$.value}\n\t\t\t\t\taria-valuemin={20}\n\t\t\t\t\taria-valuemax={80}\n\t\t\t\t\taria-label={this.$.label}\n\t\t\t\t></div>\n\t\t\t\t<div class=\"rui-window-splitter__pane\">\n\t\t\t\t\t<slot name=\"secondary\"></slot>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t}\n}\n", "import type { JsxRenderable } from '@ecopages/jsx';\n\nconst RADIANT_VIEW_ELEMENT = Symbol.for('@ecopages/storybook-radiant.viewElement');\nconst RADIANT_SCRIPT_MODULE = Symbol.for('@ecopages/storybook-radiant.scriptModule');\nconst RADIANT_SCRIPT_EXPORT = Symbol.for('@ecopages/storybook-radiant.scriptExport');\n\nexport type RadiantViewComponent<TArgs = unknown> = ((args: TArgs) => JsxRenderable) & {\n\t[RADIANT_VIEW_ELEMENT]?: CustomElementConstructor;\n\t[RADIANT_SCRIPT_MODULE]?: string;\n\t[RADIANT_SCRIPT_EXPORT]?: string;\n};\n\nfunction linkViewToElement<TArgs>(\n\tview: RadiantViewComponent<TArgs>,\n\telement: CustomElementConstructor & {\n\t\t[RADIANT_SCRIPT_MODULE]?: string;\n\t\t[RADIANT_SCRIPT_EXPORT]?: string;\n\t},\n): void {\n\tview[RADIANT_VIEW_ELEMENT] = element;\n\n\tconst ssrModule = element[RADIANT_SCRIPT_MODULE];\n\tif (ssrModule) {\n\t\tview[RADIANT_SCRIPT_MODULE] = ssrModule;\n\t\tview[RADIANT_SCRIPT_EXPORT] = element[RADIANT_SCRIPT_EXPORT] ?? element.name;\n\t}\n}\n\n/** Link a JSX view export to its RadiantElement class (same symbols as the Storybook framework). */\nexport function defineRadiantView<TArgs>(\n\telement: CustomElementConstructor & {\n\t\t[RADIANT_SCRIPT_MODULE]?: string;\n\t\t[RADIANT_SCRIPT_EXPORT]?: string;\n\t},\n\trender: (args: TArgs) => JsxRenderable,\n): RadiantViewComponent<TArgs> {\n\tconst view = ((args: TArgs) => render(args)) as RadiantViewComponent<TArgs>;\n\tlinkViewToElement(view, element);\n\treturn view;\n}\n\n/** Re-copy SSR metadata from the linked element (e.g. after HMR). */\nexport function syncRadiantViewMetadata(view: RadiantViewComponent): void {\n\tconst element = view[RADIANT_VIEW_ELEMENT];\n\tif (element) {\n\t\tlinkViewToElement(view, element);\n\t}\n}\n", "import type { JsxRenderable } from '@ecopages/jsx';\nimport type { RadiantSlotProps } from '../../../types';\nimport { defineRadiantView } from '../../../lib/radiant-view';\nimport type { RuiWindowSplitterProps } from './window-splitter.script';\nimport { RuiWindowSplitter as RuiWindowSplitterElement } from './window-splitter.script';\nimport './window-splitter.css';\n\nexport const RuiWindowSplitter = defineRadiantView(\n\tRuiWindowSplitterElement,\n\t({\n\t\tslot,\n\t\tvalue,\n\t\torientation,\n\t\tlabel,\n\t\tprimary,\n\t\tsecondary,\n\t}: RuiWindowSplitterProps & RadiantSlotProps & { primary: JsxRenderable; secondary: JsxRenderable }) => (\n\t\t<rui-window-splitter slot={slot} value={value} orientation={orientation} label={label}>\n\t\t\t<div slot=\"primary\">{primary}</div>\n\t\t\t<div slot=\"secondary\">{secondary}</div>\n\t\t</rui-window-splitter>\n\t),\n);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["RadiantElement", "bound", "customElement", "event", "onEvent", "onUpdated", "prop", "query", "RuiWindowSplitter", "orientation", "size", "delta", "horizontal", "next", "rect", "RADIANT_VIEW_ELEMENT", "RADIANT_SCRIPT_MODULE", "RADIANT_SCRIPT_EXPORT", "linkViewToElement", "view", "element", "ssrModule", "defineRadiantView", "render", "args", "RuiWindowSplitter", "defineRadiantView", "slot", "value", "orientation", "label", "primary", "secondary"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@reference '../../../styles/radiant-ui.css';
|
|
2
|
+
|
|
3
|
+
rui-window-splitter {
|
|
4
|
+
@apply block h-64 w-full;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
@layer components {
|
|
8
|
+
.rui-window-splitter {
|
|
9
|
+
@apply flex h-full w-full overflow-hidden rounded-container border border-border;
|
|
10
|
+
}
|
|
11
|
+
.rui-window-splitter--vertical {
|
|
12
|
+
@apply flex-col;
|
|
13
|
+
}
|
|
14
|
+
.rui-window-splitter__pane {
|
|
15
|
+
@apply min-h-0 min-w-0 flex-1 overflow-auto bg-background p-3 text-sm;
|
|
16
|
+
}
|
|
17
|
+
.rui-window-splitter--horizontal > .rui-window-splitter__pane:first-child {
|
|
18
|
+
flex: 0 0 auto;
|
|
19
|
+
}
|
|
20
|
+
.rui-window-splitter--vertical > .rui-window-splitter__pane:first-child {
|
|
21
|
+
flex: 0 0 auto;
|
|
22
|
+
}
|
|
23
|
+
.rui-window-splitter__separator {
|
|
24
|
+
@apply shrink-0 bg-border;
|
|
25
|
+
}
|
|
26
|
+
.rui-window-splitter--horizontal > .rui-window-splitter__separator {
|
|
27
|
+
@apply w-1 cursor-col-resize;
|
|
28
|
+
}
|
|
29
|
+
.rui-window-splitter--vertical > .rui-window-splitter__separator {
|
|
30
|
+
@apply h-1 cursor-row-resize;
|
|
31
|
+
}
|
|
32
|
+
.rui-window-splitter__separator:focus-visible {
|
|
33
|
+
@apply outline-none ring-2 ring-focus-ring;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { JsxRenderable } from '@ecopages/jsx';
|
|
2
|
+
import type { RadiantSlotProps } from '../../../types';
|
|
3
|
+
import type { RuiWindowSplitterProps } from './window-splitter.script';
|
|
4
|
+
import './window-splitter.css';
|
|
5
|
+
export declare const RuiWindowSplitter: import("../../../lib/radiant-view").RadiantViewComponent<RuiWindowSplitterProps & RadiantSlotProps & {
|
|
6
|
+
primary: JsxRenderable;
|
|
7
|
+
secondary: JsxRenderable;
|
|
8
|
+
}>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { RadiantElement } from '@ecopages/radiant';
|
|
2
|
+
import type { EventEmitter } from '@ecopages/radiant/tools/event-emitter';
|
|
3
|
+
export type RuiWindowSplitterProps = {
|
|
4
|
+
/** Primary pane size as a percentage. Default: `50`. */
|
|
5
|
+
value?: number;
|
|
6
|
+
/** Orientation of the split. Default: `horizontal` (left/right panes). */
|
|
7
|
+
orientation?: 'horizontal' | 'vertical';
|
|
8
|
+
label?: string;
|
|
9
|
+
};
|
|
10
|
+
export type RuiWindowSplitterChangeDetail = {
|
|
11
|
+
value: number;
|
|
12
|
+
};
|
|
13
|
+
type RuiWindowSplitterBindings = {
|
|
14
|
+
value: number;
|
|
15
|
+
label: string;
|
|
16
|
+
orientation: NonNullable<RuiWindowSplitterProps['orientation']>;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* `<rui-window-splitter>` — a movable separator between two panes.
|
|
20
|
+
*
|
|
21
|
+
* Implements the APG Window Splitter pattern with a focusable separator that
|
|
22
|
+
* adjusts pane size via arrow keys and pointer drag. `value` and `orientation`
|
|
23
|
+
* are reactive props.
|
|
24
|
+
*
|
|
25
|
+
* @see https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/
|
|
26
|
+
* @element rui-window-splitter
|
|
27
|
+
*/
|
|
28
|
+
export declare class RuiWindowSplitter extends RadiantElement<RuiWindowSplitterBindings> {
|
|
29
|
+
value: number;
|
|
30
|
+
orientation: NonNullable<RuiWindowSplitterProps['orientation']>;
|
|
31
|
+
label: string;
|
|
32
|
+
primaryTarget: HTMLElement;
|
|
33
|
+
separatorTarget: HTMLElement;
|
|
34
|
+
changeEvent: EventEmitter<RuiWindowSplitterChangeDetail>;
|
|
35
|
+
/** `class` stays a plain-read composition; only the derived aria-orientation string is bound. */
|
|
36
|
+
private readonly resolvedAriaOrientation;
|
|
37
|
+
private dragging;
|
|
38
|
+
connectedCallback(): void;
|
|
39
|
+
disconnectedCallback(): void;
|
|
40
|
+
onPropsUpdated(): void;
|
|
41
|
+
private applySize;
|
|
42
|
+
onKeydown(event: KeyboardEvent): void;
|
|
43
|
+
private updateValue;
|
|
44
|
+
onPointerDown(event: PointerEvent): void;
|
|
45
|
+
onPointerMove(event: PointerEvent): void;
|
|
46
|
+
onPointerUp(): void;
|
|
47
|
+
render(): import("@ecopages/jsx").JsxRenderable;
|
|
48
|
+
}
|
|
49
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated by scripts/generate-exports.ts — do not edit by hand.
|
|
3
|
+
* Importing the root entry registers every radiant-ui custom element.
|
|
4
|
+
*/
|
|
5
|
+
export * from './components/ui/alert';
|
|
6
|
+
export * from './components/ui/breadcrumb';
|
|
7
|
+
export * from './components/ui/button';
|
|
8
|
+
export * from './components/ui/carousel';
|
|
9
|
+
export * from './components/ui/checkbox';
|
|
10
|
+
export * from './components/ui/combobox';
|
|
11
|
+
export * from './components/ui/dialog';
|
|
12
|
+
export * from './components/ui/disclosure';
|
|
13
|
+
export * from './components/ui/feed';
|
|
14
|
+
export * from './components/ui/field';
|
|
15
|
+
export * from './components/ui/form';
|
|
16
|
+
export * from './components/ui/grid';
|
|
17
|
+
export * from './components/ui/input';
|
|
18
|
+
export * from './components/ui/label';
|
|
19
|
+
export * from './components/ui/listbox';
|
|
20
|
+
export * from './components/ui/menu-button';
|
|
21
|
+
export * from './components/ui/menubar';
|
|
22
|
+
export * from './components/ui/meter';
|
|
23
|
+
export * from './components/ui/navigation-menu';
|
|
24
|
+
export * from './components/ui/radio-group';
|
|
25
|
+
export * from './components/ui/sidebar';
|
|
26
|
+
export * from './components/ui/slider';
|
|
27
|
+
export * from './components/ui/spinbutton';
|
|
28
|
+
export * from './components/ui/switch';
|
|
29
|
+
export * from './components/ui/tabs';
|
|
30
|
+
export * from './components/ui/textarea';
|
|
31
|
+
export * from './components/ui/toast';
|
|
32
|
+
export * from './components/ui/toolbar';
|
|
33
|
+
export * from './components/ui/tooltip';
|
|
34
|
+
export * from './components/ui/tree';
|
|
35
|
+
export * from './components/ui/treegrid';
|
|
36
|
+
export * from './components/ui/window-splitter';
|