@ankhorage/zora 23.1.0 → 23.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/features/tree-view/adapters/inbound/TreeItem.d.ts.map +1 -1
- package/dist/features/tree-view/adapters/inbound/TreeItem.js +2 -1
- package/dist/features/tree-view/adapters/inbound/TreeItem.js.map +1 -1
- package/dist/features/tree-view/adapters/inbound/web-artifact/TreeItemRow.d.ts.map +1 -1
- package/dist/features/tree-view/adapters/inbound/web-artifact/TreeItemRow.js +5 -4
- package/dist/features/tree-view/adapters/inbound/web-artifact/TreeItemRow.js.map +1 -1
- package/dist/features/tree-view/adapters/inbound/web-artifact/TreeView.d.ts +1 -0
- package/dist/features/tree-view/adapters/inbound/web-artifact/TreeView.d.ts.map +1 -1
- package/dist/features/tree-view/adapters/inbound/web-artifact/TreeView.js.map +1 -1
- package/dist/types/tree-view.d.ts +1 -0
- package/dist/types/tree-view.d.ts.map +1 -1
- package/dist/types/tree-view.js.map +1 -1
- package/package.json +1 -1
- package/src/features/tree-view/adapters/inbound/TreeItem.tsx +3 -2
- package/src/features/tree-view/adapters/inbound/web-artifact/TreeItemRow.tsx +12 -3
- package/src/features/tree-view/adapters/inbound/web-artifact/TreeView.test.tsx +19 -0
- package/src/features/tree-view/adapters/inbound/web-artifact/TreeView.tsx +1 -0
- package/src/types/tree-view.ts +1 -0
- package/web-dist/components/tree-item/TreeItem.js +4 -3
- package/web-dist/components/tree-view/TreeView.d.ts +1 -0
- package/web-dist/components/tree-view/TreeView.js +5 -2
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# @ankhorage/zora
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.
|
|
9
9
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeItem.d.ts","sourceRoot":"","sources":["../../../../../src/features/tree-view/adapters/inbound/TreeItem.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAQrF,UAAU,aAAa,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa;IACxE,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC;IACzC,WAAW,EAAE,SAAS,GAAG,EAAE,CAAC;IAC5B,WAAW,EAAE,SAAS,GAAG,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACtD,cAAc,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;CACnE;
|
|
1
|
+
{"version":3,"file":"TreeItem.d.ts","sourceRoot":"","sources":["../../../../../src/features/tree-view/adapters/inbound/TreeItem.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAQrF,UAAU,aAAa,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa;IACxE,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC;IACzC,WAAW,EAAE,SAAS,GAAG,EAAE,CAAC;IAC5B,WAAW,EAAE,SAAS,GAAG,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACtD,cAAc,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,IAAI,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;CACnE;AAoHD,oDAAoD;AACpD,eAAO,MAAM,QAAQ,GAlHE,GAAG,SAAS,MAAM,kEAkHgB,CAAC"}
|
|
@@ -23,9 +23,10 @@ function TreeItemInner({ themeId: _themeId, mode: _mode, node, depth, expansionI
|
|
|
23
23
|
hasChildren,
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
|
+
const nodeIcon = isExpanded ? (node.expandedIcon ?? node.icon) : node.icon;
|
|
26
27
|
const listItemProps = {
|
|
27
28
|
title: node.label,
|
|
28
|
-
leading: expansionIndicator === 'folder' ||
|
|
29
|
+
leading: expansionIndicator === 'folder' || nodeIcon === undefined ? undefined : (<Icon {...nodeIcon} size={12}/>),
|
|
29
30
|
meta: node.meta,
|
|
30
31
|
disabled: node.disabled,
|
|
31
32
|
selected: isSelected,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeItem.js","sourceRoot":"","sources":["../../../../../src/features/tree-view/adapters/inbound/TreeItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oDAAoD,CAAC;AAaxF,qGAAqG;AACrG,SAAS,aAAa,CAA8B,EAClD,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,KAAK,EACX,IAAI,EACJ,KAAK,EACL,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,QAAQ,EACR,cAAc,EACd,UAAU,EACV,MAAM,EACN,iBAAiB,GACE;IACnB,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5E,MAAM,UAAU,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEjD,4FAA4F;IAC5F,MAAM,aAAa,GAAG,GAAG,EAAE;QACzB,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,UAAU,CAAC;gBAChB,IAAI;gBACJ,KAAK;gBACL,QAAQ,EAAE,UAAU;gBACpB,QAAQ,EAAE,UAAU;gBACpB,WAAW;aACZ,CAAC,CAAC;QACL,CAAC;QAED,MAAM,aAAa,GAAG;YACpB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EACL,kBAAkB,KAAK,QAAQ,IAAI,
|
|
1
|
+
{"version":3,"file":"TreeItem.js","sourceRoot":"","sources":["../../../../../src/features/tree-view/adapters/inbound/TreeItem.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Pressable } from '@ankhorage/surface';\nimport type { SelectionIntent } from '@ankhorage/utility/selection';\nimport React from 'react';\nimport { Platform } from 'react-native';\n\nimport type { ZoraBaseProps } from '../../../../types/base';\nimport type { TreeItemNode, TreeItemRenderProps } from '../../../../types/tree-view';\nimport { IconButton } from '../../../button/public';\nimport { Icon } from '../../../icon/public';\nimport { View } from '../../../layout/public';\nimport { ListItem } from '../../../list/public';\nimport { resolveSelectionEventIntent } from '../../../selection/public';\nimport { withZoraThemeScope } from '../../../theme/adapters/inbound/withZoraThemeScope';\n\ninterface TreeItemProps<TId extends string = string> extends ZoraBaseProps {\n node: TreeItemNode<TId>;\n depth: number;\n expansionIndicator: 'chevron' | 'folder';\n selectedIds: readonly TId[];\n expandedIds: readonly TId[];\n onSelect?: (id: TId, intent: SelectionIntent) => void;\n onToggleExpand: (id: TId) => void;\n renderItem?: (props: TreeItemRenderProps<TId>) => React.ReactNode;\n}\n\n/*** Render one recursive themed tree row and keep row selection separate from expansion controls. */\nfunction TreeItemInner<TId extends string = string>({\n themeId: _themeId,\n mode: _mode,\n node,\n depth,\n expansionIndicator,\n selectedIds,\n expandedIds,\n onSelect,\n onToggleExpand,\n renderItem,\n testID,\n interactionPolicy,\n}: TreeItemProps<TId>) {\n const hasChildren = node.children !== undefined && node.children.length > 0;\n const isExpanded = expandedIds.includes(node.id);\n const isSelected = selectedIds.includes(node.id);\n\n /*** Compose custom content or the selectable row independently of the expansion control. */\n const renderContent = () => {\n if (renderItem) {\n return renderItem({\n node,\n depth,\n selected: isSelected,\n expanded: isExpanded,\n hasChildren,\n });\n }\n\n const nodeIcon = isExpanded ? (node.expandedIcon ?? node.icon) : node.icon;\n const listItemProps = {\n title: node.label,\n leading:\n expansionIndicator === 'folder' || nodeIcon === undefined ? undefined : (\n <Icon {...nodeIcon} size={12} />\n ),\n meta: node.meta,\n disabled: node.disabled,\n selected: isSelected,\n trailing: node.actions,\n };\n\n if (onSelect === undefined) return <ListItem {...listItemProps} />;\n return (\n <Pressable\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: node.disabled, selected: isSelected }}\n disabled={node.disabled}\n interactionPolicy={interactionPolicy}\n onPress={(event) =>\n onSelect(\n node.id,\n resolveSelectionEventIntent(event, Platform.OS === 'web' ? 'pointer' : 'touch'),\n )\n }\n >\n <ListItem {...listItemProps} />\n </Pressable>\n );\n };\n\n return (\n <View testID={testID}>\n <View direction=\"row\" align=\"center\" style={{ paddingLeft: depth * 16 }}>\n {hasChildren ? (\n <IconButton\n icon={{\n name:\n expansionIndicator === 'folder'\n ? isExpanded\n ? 'folder-open-outline'\n : 'folder-outline'\n : isExpanded\n ? 'chevron-down-outline'\n : 'chevron-forward-outline',\n }}\n disabled={node.disabled}\n interactionPolicy={interactionPolicy}\n label={isExpanded ? 'Collapse' : 'Expand'}\n onPress={() => onToggleExpand(node.id)}\n size=\"s\"\n variant=\"ghost\"\n />\n ) : (\n <View style={{ width: 32 }} align=\"center\">\n {expansionIndicator === 'folder' ? <Icon name=\"document-outline\" size=\"s\" /> : null}\n </View>\n )}\n <View style={{ flex: 1, minWidth: 0 }}>{renderContent()}</View>\n </View>\n {hasChildren && isExpanded ? (\n <View>\n {node.children?.map((child) => (\n <TreeItem\n key={child.id}\n depth={depth + 1}\n expandedIds={expandedIds}\n expansionIndicator={expansionIndicator}\n interactionPolicy={interactionPolicy}\n node={child}\n onSelect={onSelect}\n onToggleExpand={onToggleExpand}\n renderItem={renderItem}\n selectedIds={selectedIds}\n />\n ))}\n </View>\n ) : null}\n </View>\n );\n}\n\n/*** Single tree node row used within `TreeView`. */\nexport const TreeItem = withZoraThemeScope(TreeItemInner);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeItemRow.d.ts","sourceRoot":"","sources":["../../../../../../src/features/tree-view/adapters/inbound/web-artifact/TreeItemRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEpE,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,GAAG,SAAS,MAAM,EAAE,KAAK,EAAE,gBAAgB,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"TreeItemRow.d.ts","sourceRoot":"","sources":["../../../../../../src/features/tree-view/adapters/inbound/web-artifact/TreeItemRow.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEpE,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,GAAG,SAAS,MAAM,EAAE,KAAK,EAAE,gBAAgB,CAAC,GAAG,CAAC,qBA8C3E;AAED,UAAU,gBAAgB,CAAC,GAAG,SAAS,MAAM;IAC3C,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,kBAAkB,EAAE,SAAS,GAAG,QAAQ,CAAC;IAClD,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,EAAE,CAAC;IACrC,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,EAAE,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/D,QAAQ,CAAC,cAAc,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;CAC5E"}
|
|
@@ -13,7 +13,7 @@ export function TreeItemRow(props) {
|
|
|
13
13
|
selected,
|
|
14
14
|
expanded,
|
|
15
15
|
hasChildren,
|
|
16
|
-
}) ?? <TreeItemDefaultContent node={node} showIcon={props.expansionIndicator === 'chevron'}
|
|
16
|
+
}) ?? (<TreeItemDefaultContent expanded={expanded} node={node} showIcon={props.expansionIndicator === 'chevron'}/>);
|
|
17
17
|
return (<>
|
|
18
18
|
<div aria-disabled={node.disabled === true ? true : undefined} aria-expanded={hasChildren ? expanded : undefined} aria-selected={selected} onPointerUp={(event) => selectNode(event, props)} onClick={(event) => selectNodeFromSyntheticClick(event, props)} onKeyDown={(event) => selectNodeFromKeyboard(event, props)} role="treeitem" tabIndex={node.disabled || props.onSelect === undefined ? undefined : 0} style={createRowStyle(props.depth, selected, node.disabled, props.onSelect !== undefined)}>
|
|
19
19
|
<TreeItemExpander disabled={node.disabled} expanded={expanded} indicator={props.expansionIndicator} hasChildren={hasChildren} nodeId={node.id} onToggleExpand={props.onToggleExpand}/>
|
|
@@ -24,10 +24,11 @@ export function TreeItemRow(props) {
|
|
|
24
24
|
</>);
|
|
25
25
|
}
|
|
26
26
|
/*** Render the default browser tree-row label, icon, and metadata. */
|
|
27
|
-
function TreeItemDefaultContent({ node, showIcon, }) {
|
|
27
|
+
function TreeItemDefaultContent({ expanded, node, showIcon, }) {
|
|
28
|
+
const icon = expanded ? (node.expandedIcon ?? node.icon) : node.icon;
|
|
28
29
|
return (<>
|
|
29
|
-
{!showIcon ||
|
|
30
|
-
{
|
|
30
|
+
{!showIcon || icon === undefined ? null : (<span aria-hidden="true" style={ICON_STYLE}>
|
|
31
|
+
{icon}
|
|
31
32
|
</span>)}
|
|
32
33
|
<span style={LABEL_STYLE}>{node.label}</span>
|
|
33
34
|
{node.meta === undefined ? null : <span style={META_STYLE}>{node.meta}</span>}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeItemRow.js","sourceRoot":"","sources":["../../../../../../src/features/tree-view/adapters/inbound/web-artifact/TreeItemRow.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { SelectionIntent } from '@ankhorage/utility/selection';\nimport React from 'react';\n\nimport { resolveSelectionEventIntent } from '../../../../selection/application/resolveSelectionEventIntent';\nimport { TreeExpansionIndicator } from './TreeExpansionIndicator';\nimport type { TreeItemNode, TreeItemRenderProps } from './TreeView';\n\n/*** Render one recursive browser tree row while keeping selection and expansion independent. */\nexport function TreeItemRow<TId extends string>(props: TreeItemRowProps<TId>) {\n const { node } = props;\n const hasChildren = node.children !== undefined && node.children.length > 0;\n const expanded = props.expandedIds.includes(node.id);\n const selected = props.selectedIds.includes(node.id);\n const content = props.renderItem?.({\n node,\n depth: props.depth,\n selected,\n expanded,\n hasChildren,\n }) ?? <TreeItemDefaultContent node={node} showIcon={props.expansionIndicator === 'chevron'} />;\n\n return (\n <>\n <div\n aria-disabled={node.disabled === true ? true : undefined}\n aria-expanded={hasChildren ? expanded : undefined}\n aria-selected={selected}\n onPointerUp={(event) => selectNode(event, props)}\n onClick={(event) => selectNodeFromSyntheticClick(event, props)}\n onKeyDown={(event) => selectNodeFromKeyboard(event, props)}\n role=\"treeitem\"\n tabIndex={node.disabled || props.onSelect === undefined ? undefined : 0}\n style={createRowStyle(props.depth, selected, node.disabled, props.onSelect !== undefined)}\n >\n <TreeItemExpander\n disabled={node.disabled}\n expanded={expanded}\n indicator={props.expansionIndicator}\n hasChildren={hasChildren}\n nodeId={node.id}\n onToggleExpand={props.onToggleExpand}\n />\n {content}\n <TreeItemActions actions={node.actions} />\n </div>\n {hasChildren && expanded ? <TreeItemChildren {...props} /> : null}\n </>\n );\n}\n\ninterface TreeItemRowProps<TId extends string> {\n readonly node: TreeItemNode<TId>;\n readonly depth: number;\n readonly expansionIndicator: 'chevron' | 'folder';\n readonly selectedIds: readonly TId[];\n readonly expandedIds: readonly TId[];\n readonly onSelect?: (id: TId, intent: SelectionIntent) => void;\n readonly onToggleExpand: (id: TId) => void;\n readonly renderItem?: (props: TreeItemRenderProps<TId>) => React.ReactNode;\n}\n\n/*** Render the default browser tree-row label, icon, and metadata. */\nfunction TreeItemDefaultContent<TId extends string>({\n node,\n showIcon,\n}: {\n readonly node: TreeItemNode<TId>;\n readonly showIcon: boolean;\n}) {\n return (\n <>\n {!showIcon || node.icon === undefined ? null : (\n <span aria-hidden=\"true\" style={ICON_STYLE}>\n {node.icon}\n </span>\n )}\n <span style={LABEL_STYLE}>{node.label}</span>\n {node.meta === undefined ? null : <span style={META_STYLE}>{node.meta}</span>}\n </>\n );\n}\n\n/*** Isolate optional row actions so their pointer and keyboard events do not select the tree item. */\nfunction TreeItemActions({ actions }: { readonly actions?: React.ReactNode }) {\n if (actions === undefined) return null;\n return (\n <span\n onClick={(event) => event.stopPropagation()}\n onPointerUp={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n style={INLINE_STYLE}\n >\n {actions}\n </span>\n );\n}\n\n/*** Render the independent expansion control for a tree row with children. */\nfunction TreeItemExpander<TId extends string>(props: {\n readonly disabled?: boolean;\n readonly expanded: boolean;\n readonly indicator: 'chevron' | 'folder';\n readonly hasChildren: boolean;\n readonly nodeId: TId;\n readonly onToggleExpand: (id: TId) => void;\n}) {\n const indicator = (\n <TreeExpansionIndicator\n expanded={props.expanded}\n hasChildren={props.hasChildren}\n variant={props.indicator}\n />\n );\n if (!props.hasChildren)\n return (\n <span aria-hidden=\"true\" style={EXPANDER_STYLE}>\n {indicator}\n </span>\n );\n return (\n <button\n aria-label={props.expanded ? 'Collapse' : 'Expand'}\n disabled={props.disabled}\n onKeyDown={(event) => event.stopPropagation()}\n onPointerUp={(event) => event.stopPropagation()}\n onClick={(event) => {\n event.stopPropagation();\n props.onToggleExpand(props.nodeId);\n }}\n style={EXPANDER_STYLE}\n type=\"button\"\n >\n {indicator}\n </button>\n );\n}\n\n/*** Render expanded descendants recursively. */\nfunction TreeItemChildren<TId extends string>(props: TreeItemRowProps<TId>) {\n return (\n <div role=\"group\">\n {props.node.children?.map((child) => (\n <TreeItemRow {...props} key={child.id} depth={props.depth + 1} node={child} />\n ))}\n </div>\n );\n}\n\n/*** Select a row from pointer activation when it is interactive. */\nfunction selectNode<TId extends string>(\n event: React.PointerEvent<HTMLDivElement>,\n props: TreeItemRowProps<TId>,\n) {\n if (props.node.disabled) return;\n props.onSelect?.(props.node.id, resolveSelectionEventIntent(event, 'pointer'));\n}\n\n/*** Select a row from assistive or synthetic click activation without duplicating pointer clicks. */\nfunction selectNodeFromSyntheticClick<TId extends string>(\n event: React.MouseEvent<HTMLDivElement>,\n props: TreeItemRowProps<TId>,\n) {\n if (event.detail !== 0 || props.node.disabled) return;\n props.onSelect?.(props.node.id, resolveSelectionEventIntent(event, 'keyboard'));\n}\n\n/*** Select a row from keyboard activation while preserving native navigation keys. */\nfunction selectNodeFromKeyboard<TId extends string>(\n event: React.KeyboardEvent<HTMLDivElement>,\n props: TreeItemRowProps<TId>,\n) {\n if (props.node.disabled || (event.key !== 'Enter' && event.key !== ' ')) return;\n event.preventDefault();\n props.onSelect?.(props.node.id, resolveSelectionEventIntent(event, 'keyboard'));\n}\n\n/*** Resolve browser row presentation from the interaction state. */\nfunction createRowStyle(\n depth: number,\n selected: boolean,\n disabled: boolean | undefined,\n selectable: boolean,\n): React.CSSProperties {\n return {\n ...ROW_STYLE,\n background: selected ? 'color-mix(in srgb, currentColor 10%, transparent)' : 'transparent',\n cursor: disabled ? 'default' : selectable ? 'pointer' : 'inherit',\n opacity: disabled ? 0.5 : 1,\n paddingLeft: depth * 16 + 6,\n };\n}\n\nconst ROW_STYLE = {\n alignItems: 'center',\n borderRadius: 6,\n display: 'flex',\n gap: 6,\n minHeight: 28,\n paddingRight: 4,\n userSelect: 'none',\n} as const satisfies React.CSSProperties;\n\nconst INLINE_STYLE = {\n display: 'inline-flex',\n flexShrink: 0,\n} as const satisfies React.CSSProperties;\n\nconst ICON_STYLE = INLINE_STYLE;\n\nconst LABEL_STYLE = {\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n} as const satisfies React.CSSProperties;\n\nconst META_STYLE = {\n flexShrink: 0,\n opacity: 0.65,\n} as const satisfies React.CSSProperties;\n\nconst EXPANDER_STYLE = {\n alignItems: 'center',\n appearance: 'none',\n background: 'transparent',\n border: 0,\n color: 'inherit',\n cursor: 'pointer',\n display: 'inline-flex',\n flexShrink: 0,\n font: 'inherit',\n height: 24,\n justifyContent: 'center',\n padding: 0,\n width: 24,\n} as const satisfies React.CSSProperties;\n"]}
|
|
1
|
+
{"version":3,"file":"TreeItemRow.js","sourceRoot":"","sources":["../../../../../../src/features/tree-view/adapters/inbound/web-artifact/TreeItemRow.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { SelectionIntent } from '@ankhorage/utility/selection';\nimport React from 'react';\n\nimport { resolveSelectionEventIntent } from '../../../../selection/application/resolveSelectionEventIntent';\nimport { TreeExpansionIndicator } from './TreeExpansionIndicator';\nimport type { TreeItemNode, TreeItemRenderProps } from './TreeView';\n\n/*** Render one recursive browser tree row while keeping selection and expansion independent. */\nexport function TreeItemRow<TId extends string>(props: TreeItemRowProps<TId>) {\n const { node } = props;\n const hasChildren = node.children !== undefined && node.children.length > 0;\n const expanded = props.expandedIds.includes(node.id);\n const selected = props.selectedIds.includes(node.id);\n const content = props.renderItem?.({\n node,\n depth: props.depth,\n selected,\n expanded,\n hasChildren,\n }) ?? (\n <TreeItemDefaultContent\n expanded={expanded}\n node={node}\n showIcon={props.expansionIndicator === 'chevron'}\n />\n );\n\n return (\n <>\n <div\n aria-disabled={node.disabled === true ? true : undefined}\n aria-expanded={hasChildren ? expanded : undefined}\n aria-selected={selected}\n onPointerUp={(event) => selectNode(event, props)}\n onClick={(event) => selectNodeFromSyntheticClick(event, props)}\n onKeyDown={(event) => selectNodeFromKeyboard(event, props)}\n role=\"treeitem\"\n tabIndex={node.disabled || props.onSelect === undefined ? undefined : 0}\n style={createRowStyle(props.depth, selected, node.disabled, props.onSelect !== undefined)}\n >\n <TreeItemExpander\n disabled={node.disabled}\n expanded={expanded}\n indicator={props.expansionIndicator}\n hasChildren={hasChildren}\n nodeId={node.id}\n onToggleExpand={props.onToggleExpand}\n />\n {content}\n <TreeItemActions actions={node.actions} />\n </div>\n {hasChildren && expanded ? <TreeItemChildren {...props} /> : null}\n </>\n );\n}\n\ninterface TreeItemRowProps<TId extends string> {\n readonly node: TreeItemNode<TId>;\n readonly depth: number;\n readonly expansionIndicator: 'chevron' | 'folder';\n readonly selectedIds: readonly TId[];\n readonly expandedIds: readonly TId[];\n readonly onSelect?: (id: TId, intent: SelectionIntent) => void;\n readonly onToggleExpand: (id: TId) => void;\n readonly renderItem?: (props: TreeItemRenderProps<TId>) => React.ReactNode;\n}\n\n/*** Render the default browser tree-row label, icon, and metadata. */\nfunction TreeItemDefaultContent<TId extends string>({\n expanded,\n node,\n showIcon,\n}: {\n readonly expanded: boolean;\n readonly node: TreeItemNode<TId>;\n readonly showIcon: boolean;\n}) {\n const icon = expanded ? (node.expandedIcon ?? node.icon) : node.icon;\n return (\n <>\n {!showIcon || icon === undefined ? null : (\n <span aria-hidden=\"true\" style={ICON_STYLE}>\n {icon}\n </span>\n )}\n <span style={LABEL_STYLE}>{node.label}</span>\n {node.meta === undefined ? null : <span style={META_STYLE}>{node.meta}</span>}\n </>\n );\n}\n\n/*** Isolate optional row actions so their pointer and keyboard events do not select the tree item. */\nfunction TreeItemActions({ actions }: { readonly actions?: React.ReactNode }) {\n if (actions === undefined) return null;\n return (\n <span\n onClick={(event) => event.stopPropagation()}\n onPointerUp={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n style={INLINE_STYLE}\n >\n {actions}\n </span>\n );\n}\n\n/*** Render the independent expansion control for a tree row with children. */\nfunction TreeItemExpander<TId extends string>(props: {\n readonly disabled?: boolean;\n readonly expanded: boolean;\n readonly indicator: 'chevron' | 'folder';\n readonly hasChildren: boolean;\n readonly nodeId: TId;\n readonly onToggleExpand: (id: TId) => void;\n}) {\n const indicator = (\n <TreeExpansionIndicator\n expanded={props.expanded}\n hasChildren={props.hasChildren}\n variant={props.indicator}\n />\n );\n if (!props.hasChildren)\n return (\n <span aria-hidden=\"true\" style={EXPANDER_STYLE}>\n {indicator}\n </span>\n );\n return (\n <button\n aria-label={props.expanded ? 'Collapse' : 'Expand'}\n disabled={props.disabled}\n onKeyDown={(event) => event.stopPropagation()}\n onPointerUp={(event) => event.stopPropagation()}\n onClick={(event) => {\n event.stopPropagation();\n props.onToggleExpand(props.nodeId);\n }}\n style={EXPANDER_STYLE}\n type=\"button\"\n >\n {indicator}\n </button>\n );\n}\n\n/*** Render expanded descendants recursively. */\nfunction TreeItemChildren<TId extends string>(props: TreeItemRowProps<TId>) {\n return (\n <div role=\"group\">\n {props.node.children?.map((child) => (\n <TreeItemRow {...props} key={child.id} depth={props.depth + 1} node={child} />\n ))}\n </div>\n );\n}\n\n/*** Select a row from pointer activation when it is interactive. */\nfunction selectNode<TId extends string>(\n event: React.PointerEvent<HTMLDivElement>,\n props: TreeItemRowProps<TId>,\n) {\n if (props.node.disabled) return;\n props.onSelect?.(props.node.id, resolveSelectionEventIntent(event, 'pointer'));\n}\n\n/*** Select a row from assistive or synthetic click activation without duplicating pointer clicks. */\nfunction selectNodeFromSyntheticClick<TId extends string>(\n event: React.MouseEvent<HTMLDivElement>,\n props: TreeItemRowProps<TId>,\n) {\n if (event.detail !== 0 || props.node.disabled) return;\n props.onSelect?.(props.node.id, resolveSelectionEventIntent(event, 'keyboard'));\n}\n\n/*** Select a row from keyboard activation while preserving native navigation keys. */\nfunction selectNodeFromKeyboard<TId extends string>(\n event: React.KeyboardEvent<HTMLDivElement>,\n props: TreeItemRowProps<TId>,\n) {\n if (props.node.disabled || (event.key !== 'Enter' && event.key !== ' ')) return;\n event.preventDefault();\n props.onSelect?.(props.node.id, resolveSelectionEventIntent(event, 'keyboard'));\n}\n\n/*** Resolve browser row presentation from the interaction state. */\nfunction createRowStyle(\n depth: number,\n selected: boolean,\n disabled: boolean | undefined,\n selectable: boolean,\n): React.CSSProperties {\n return {\n ...ROW_STYLE,\n background: selected ? 'color-mix(in srgb, currentColor 10%, transparent)' : 'transparent',\n cursor: disabled ? 'default' : selectable ? 'pointer' : 'inherit',\n opacity: disabled ? 0.5 : 1,\n paddingLeft: depth * 16 + 6,\n };\n}\n\nconst ROW_STYLE = {\n alignItems: 'center',\n borderRadius: 6,\n display: 'flex',\n gap: 6,\n minHeight: 28,\n paddingRight: 4,\n userSelect: 'none',\n} as const satisfies React.CSSProperties;\n\nconst INLINE_STYLE = {\n display: 'inline-flex',\n flexShrink: 0,\n} as const satisfies React.CSSProperties;\n\nconst ICON_STYLE = INLINE_STYLE;\n\nconst LABEL_STYLE = {\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n} as const satisfies React.CSSProperties;\n\nconst META_STYLE = {\n flexShrink: 0,\n opacity: 0.65,\n} as const satisfies React.CSSProperties;\n\nconst EXPANDER_STYLE = {\n alignItems: 'center',\n appearance: 'none',\n background: 'transparent',\n border: 0,\n color: 'inherit',\n cursor: 'pointer',\n display: 'inline-flex',\n flexShrink: 0,\n font: 'inherit',\n height: 24,\n justifyContent: 'center',\n padding: 0,\n width: 24,\n} as const satisfies React.CSSProperties;\n"]}
|
|
@@ -4,6 +4,7 @@ export interface TreeItemNode<TId extends string = string> {
|
|
|
4
4
|
readonly id: TId;
|
|
5
5
|
readonly label: React.ReactNode;
|
|
6
6
|
readonly icon?: React.ReactNode;
|
|
7
|
+
readonly expandedIcon?: React.ReactNode;
|
|
7
8
|
readonly children?: readonly TreeItemNode<TId>[];
|
|
8
9
|
readonly disabled?: boolean;
|
|
9
10
|
readonly meta?: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeView.d.ts","sourceRoot":"","sources":["../../../../../../src/features/tree-view/adapters/inbound/web-artifact/TreeView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,MAAM,WAAW,YAAY,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IACvD,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;IACjB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IAC9D,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IACxD,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IACtC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,KAAK,IAAI,CAAC;IAC1D,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC3E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,EAAE,EACpD,KAAK,EACL,WAAgB,EAChB,WAAW,EAAE,qBAAqB,EAClC,kBAAkB,EAClB,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,kBAA6B,EAC7B,SAAS,EACT,KAAK,EACL,SAAkB,GACnB,EAAE,aAAa,CAAC,GAAG,CAAC,qBAyCpB"}
|
|
1
|
+
{"version":3,"file":"TreeView.d.ts","sourceRoot":"","sources":["../../../../../../src/features/tree-view/adapters/inbound/web-artifact/TreeView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,MAAM,WAAW,YAAY,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IACvD,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;IACjB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IAC9D,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IACxD,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IACtC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,KAAK,IAAI,CAAC;IAC1D,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC3E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,EAAE,EACpD,KAAK,EACL,WAAgB,EAChB,WAAW,EAAE,qBAAqB,EAClC,kBAAkB,EAClB,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,kBAA6B,EAC7B,SAAS,EACT,KAAK,EACL,SAAkB,GACnB,EAAE,aAAa,CAAC,GAAG,CAAC,qBAyCpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreeView.js","sourceRoot":"","sources":["../../../../../../src/features/tree-view/adapters/inbound/web-artifact/TreeView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"TreeView.js","sourceRoot":"","sources":["../../../../../../src/features/tree-view/adapters/inbound/web-artifact/TreeView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAmC5C;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAA8B,EACpD,KAAK,EACL,WAAW,GAAG,EAAE,EAChB,WAAW,EAAE,qBAAqB,EAClC,kBAAkB,EAClB,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,kBAAkB,GAAG,QAAQ,EAC7B,SAAS,EACT,KAAK,EACL,SAAS,GAAG,MAAM,GACC;IACnB,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAClE,kBAAkB,IAAI,EAAE,CACzB,CAAC;IACF,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAwB,IAAI,CAAC,CAAC;IAC1D,MAAM,YAAY,GAAG,qBAAqB,KAAK,SAAS,CAAC;IACzD,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,mBAAmB,CAAC;IAC/E,MAAM,kBAAkB,GAAG,KAAK,CAAC,WAAW,CAC1C,CAAC,EAAO,EAAE,EAAE;QACV,MAAM,eAAe,GAAG,iBAAiB,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,YAAY;YAAE,sBAAsB,CAAC,eAAe,CAAC,CAAC;QAC3D,gBAAgB,EAAE,CAAC,eAAe,CAAC,CAAC;IACtC,CAAC,EACD,CAAC,WAAW,EAAE,YAAY,EAAE,gBAAgB,CAAC,CAC9C,CAAC;IACF,yBAAyB,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IAE7D,OAAO,CACL,CAAC,GAAG,CACF,GAAG,CAAC,CAAC,OAAO,CAAC,CACb,UAAU,CAAC,CAAC,SAAS,CAAC,CACtB,oBAAoB,CAAC,MAAM,CAC3B,SAAS,CAAC,CAAC,SAAS,CAAC,CACrB,IAAI,CAAC,MAAM,CACX,KAAK,CAAC,CAAC,EAAE,GAAG,UAAU,EAAE,GAAG,KAAK,EAAE,CAAC,CAEnC;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,CAAC,WAAW,CACV,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CACb,KAAK,CAAC,CAAC,CAAC,CAAC,CACT,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,kBAAkB,CAAC,CAAC,kBAAkB,CAAC,CACvC,IAAI,CAAC,CAAC,IAAI,CAAC,CACX,QAAQ,CAAC,CAAC,QAAQ,CAAC,CACnB,cAAc,CAAC,CAAC,kBAAkB,CAAC,CACnC,UAAU,CAAC,CAAC,UAAU,CAAC,CACvB,WAAW,CAAC,CAAC,WAAW,CAAC,EACzB,CACH,CAAC,CACJ;IAAA,EAAE,GAAG,CAAC,CACP,CAAC;AACJ,CAAC;AAED,wGAAwG;AACxG,SAAS,yBAAyB,CAChC,OAA+C,EAC/C,WAA2B,EAC3B,WAA2B;IAE3B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACrC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAqD,CAAC;QAC3E,IAAI;YACF,EAAE,aAAa,CAAC,yCAAyC,CAAC;YAC1D,EAAE,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,GAAG;IACjB,OAAO,EAAE,MAAM;IACf,aAAa,EAAE,QAAQ;IACvB,QAAQ,EAAE,CAAC;CAC2B,CAAC","sourcesContent":["import type { SelectionIntent } from '@ankhorage/utility/selection';\nimport React from 'react';\n\nimport { toggleExpandedIds } from '../../../utils/toggleExpandedIds';\nimport { TreeItemRow } from './TreeItemRow';\n\nexport interface TreeItemNode<TId extends string = string> {\n readonly id: TId;\n readonly label: React.ReactNode;\n readonly icon?: React.ReactNode;\n readonly expandedIcon?: React.ReactNode;\n readonly children?: readonly TreeItemNode<TId>[];\n readonly disabled?: boolean;\n readonly meta?: React.ReactNode;\n readonly actions?: React.ReactNode;\n}\n\nexport interface TreeItemRenderProps<TId extends string = string> {\n readonly node: TreeItemNode<TId>;\n readonly depth: number;\n readonly selected: boolean;\n readonly expanded: boolean;\n readonly hasChildren: boolean;\n}\n\nexport interface TreeViewProps<TId extends string = string> {\n readonly nodes: readonly TreeItemNode<TId>[];\n readonly selectedIds?: readonly TId[];\n readonly expandedIds?: readonly TId[];\n readonly defaultExpandedIds?: readonly TId[];\n readonly onSelect?: (id: TId, intent: SelectionIntent) => void;\n readonly onExpandedChange?: (ids: readonly TId[]) => void;\n readonly renderItem?: (props: TreeItemRenderProps<TId>) => React.ReactNode;\n readonly expansionIndicator?: 'chevron' | 'folder';\n readonly className?: string;\n readonly style?: React.CSSProperties;\n readonly ariaLabel?: string;\n}\n\n/***\n * Render the standalone browser TreeView artifact without React Native runtime dependencies.\n * expansionIndicator Use `chevron` beside custom node icons, or `folder` (default) for\n * built-in folder/file indicators. Expansion is leading and independent from row selection.\n */\nexport function TreeView<TId extends string = string>({\n nodes,\n selectedIds = [],\n expandedIds: controlledExpandedIds,\n defaultExpandedIds,\n onSelect,\n onExpandedChange,\n renderItem,\n expansionIndicator = 'folder',\n className,\n style,\n ariaLabel = 'Tree',\n}: TreeViewProps<TId>) {\n const [internalExpandedIds, setInternalExpandedIds] = React.useState<readonly TId[]>(\n defaultExpandedIds ?? [],\n );\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const isControlled = controlledExpandedIds !== undefined;\n const expandedIds = isControlled ? controlledExpandedIds : internalExpandedIds;\n const handleToggleExpand = React.useCallback(\n (id: TId) => {\n const nextExpandedIds = toggleExpandedIds(expandedIds, id);\n if (!isControlled) setInternalExpandedIds(nextExpandedIds);\n onExpandedChange?.(nextExpandedIds);\n },\n [expandedIds, isControlled, onExpandedChange],\n );\n useSelectedTreeItemReveal(rootRef, selectedIds, expandedIds);\n\n return (\n <div\n ref={rootRef}\n aria-label={ariaLabel}\n aria-multiselectable=\"true\"\n className={className}\n role=\"tree\"\n style={{ ...TREE_STYLE, ...style }}\n >\n {nodes.map((node) => (\n <TreeItemRow\n key={node.id}\n depth={0}\n expandedIds={expandedIds}\n expansionIndicator={expansionIndicator}\n node={node}\n onSelect={onSelect}\n onToggleExpand={handleToggleExpand}\n renderItem={renderItem}\n selectedIds={selectedIds}\n />\n ))}\n </div>\n );\n}\n\n/*** Reveal the first controlled selection after it is rendered without changing expansion ownership. */\nfunction useSelectedTreeItemReveal<TId extends string>(\n rootRef: React.RefObject<HTMLDivElement | null>,\n selectedIds: readonly TId[],\n expandedIds: readonly TId[],\n) {\n React.useEffect(() => {\n if (selectedIds.length === 0) return;\n const root = rootRef.current as unknown as TreeViewQueryableElement | null;\n root\n ?.querySelector('[role=\"treeitem\"][aria-selected=\"true\"]')\n ?.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n }, [expandedIds, rootRef, selectedIds]);\n}\n\nconst TREE_STYLE = {\n display: 'flex',\n flexDirection: 'column',\n minWidth: 0,\n} as const satisfies React.CSSProperties;\n\ninterface TreeViewQueryableElement {\n querySelector(selector: string): TreeViewRevealTarget | null;\n}\n\ninterface TreeViewRevealTarget {\n scrollIntoView(options: { readonly block: 'nearest'; readonly inline: 'nearest' }): void;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-view.d.ts","sourceRoot":"","sources":["../../src/types/tree-view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,MAAM,WAAW,YAAY,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IACvD,EAAE,EAAE,GAAG,CAAC;IACR,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,QAAQ,CAAC,EAAE,SAAS,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IAC9D,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,aAAa,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa;IAC/E,KAAK,EAAE,SAAS,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;IACpC,WAAW,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IAC7B,kBAAkB,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACtD,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,KAAK,IAAI,CAAC;IACjD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;IAC5D,kBAAkB,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC3C"}
|
|
1
|
+
{"version":3,"file":"tree-view.d.ts","sourceRoot":"","sources":["../../src/types/tree-view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,MAAM,WAAW,YAAY,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IACvD,EAAE,EAAE,GAAG,CAAC;IACR,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,EAAE,SAAS,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM;IAC9D,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,aAAa,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa;IAC/E,KAAK,EAAE,SAAS,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;IACpC,WAAW,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IAC7B,kBAAkB,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACtD,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,GAAG,EAAE,KAAK,IAAI,CAAC;IACjD,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;IAC5D,kBAAkB,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC3C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-view.js","sourceRoot":"","sources":["../../src/types/tree-view.ts"],"names":[],"mappings":"","sourcesContent":["import type { ButtonIconSpec } from '@ankhorage/surface';\nimport type { SelectionIntent } from '@ankhorage/utility/selection';\nimport type { ReactNode } from 'react';\n\nimport type { ZoraBaseProps } from './base';\n\nexport interface TreeItemNode<TId extends string = string> {\n id: TId;\n label: ReactNode;\n icon?: ButtonIconSpec;\n children?: readonly TreeItemNode<TId>[];\n disabled?: boolean;\n meta?: ReactNode;\n actions?: ReactNode;\n}\n\nexport interface TreeItemRenderProps<TId extends string = string> {\n node: TreeItemNode<TId>;\n depth: number;\n selected: boolean;\n expanded: boolean;\n hasChildren: boolean;\n}\n\nexport interface TreeViewProps<TId extends string = string> extends ZoraBaseProps {\n nodes: readonly TreeItemNode<TId>[];\n selectedIds?: readonly TId[];\n expandedIds?: readonly TId[];\n defaultExpandedIds?: readonly TId[];\n onSelect?: (id: TId, intent: SelectionIntent) => void;\n onExpandedChange?: (ids: readonly TId[]) => void;\n renderItem?: (props: TreeItemRenderProps<TId>) => ReactNode;\n expansionIndicator?: 'chevron' | 'folder';\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tree-view.js","sourceRoot":"","sources":["../../src/types/tree-view.ts"],"names":[],"mappings":"","sourcesContent":["import type { ButtonIconSpec } from '@ankhorage/surface';\nimport type { SelectionIntent } from '@ankhorage/utility/selection';\nimport type { ReactNode } from 'react';\n\nimport type { ZoraBaseProps } from './base';\n\nexport interface TreeItemNode<TId extends string = string> {\n id: TId;\n label: ReactNode;\n icon?: ButtonIconSpec;\n expandedIcon?: ButtonIconSpec;\n children?: readonly TreeItemNode<TId>[];\n disabled?: boolean;\n meta?: ReactNode;\n actions?: ReactNode;\n}\n\nexport interface TreeItemRenderProps<TId extends string = string> {\n node: TreeItemNode<TId>;\n depth: number;\n selected: boolean;\n expanded: boolean;\n hasChildren: boolean;\n}\n\nexport interface TreeViewProps<TId extends string = string> extends ZoraBaseProps {\n nodes: readonly TreeItemNode<TId>[];\n selectedIds?: readonly TId[];\n expandedIds?: readonly TId[];\n defaultExpandedIds?: readonly TId[];\n onSelect?: (id: TId, intent: SelectionIntent) => void;\n onExpandedChange?: (ids: readonly TId[]) => void;\n renderItem?: (props: TreeItemRenderProps<TId>) => ReactNode;\n expansionIndicator?: 'chevron' | 'folder';\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/zora",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "23.
|
|
4
|
+
"version": "23.2.0",
|
|
5
5
|
"description": "Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.",
|
|
6
6
|
"homepage": "https://github.com/ankhorage/zora#readme",
|
|
7
7
|
"bugs": {
|
|
@@ -54,11 +54,12 @@ function TreeItemInner<TId extends string = string>({
|
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
const nodeIcon = isExpanded ? (node.expandedIcon ?? node.icon) : node.icon;
|
|
57
58
|
const listItemProps = {
|
|
58
59
|
title: node.label,
|
|
59
60
|
leading:
|
|
60
|
-
expansionIndicator === 'folder' ||
|
|
61
|
-
<Icon {...
|
|
61
|
+
expansionIndicator === 'folder' || nodeIcon === undefined ? undefined : (
|
|
62
|
+
<Icon {...nodeIcon} size={12} />
|
|
62
63
|
),
|
|
63
64
|
meta: node.meta,
|
|
64
65
|
disabled: node.disabled,
|
|
@@ -17,7 +17,13 @@ export function TreeItemRow<TId extends string>(props: TreeItemRowProps<TId>) {
|
|
|
17
17
|
selected,
|
|
18
18
|
expanded,
|
|
19
19
|
hasChildren,
|
|
20
|
-
}) ??
|
|
20
|
+
}) ?? (
|
|
21
|
+
<TreeItemDefaultContent
|
|
22
|
+
expanded={expanded}
|
|
23
|
+
node={node}
|
|
24
|
+
showIcon={props.expansionIndicator === 'chevron'}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
21
27
|
|
|
22
28
|
return (
|
|
23
29
|
<>
|
|
@@ -61,17 +67,20 @@ interface TreeItemRowProps<TId extends string> {
|
|
|
61
67
|
|
|
62
68
|
/*** Render the default browser tree-row label, icon, and metadata. */
|
|
63
69
|
function TreeItemDefaultContent<TId extends string>({
|
|
70
|
+
expanded,
|
|
64
71
|
node,
|
|
65
72
|
showIcon,
|
|
66
73
|
}: {
|
|
74
|
+
readonly expanded: boolean;
|
|
67
75
|
readonly node: TreeItemNode<TId>;
|
|
68
76
|
readonly showIcon: boolean;
|
|
69
77
|
}) {
|
|
78
|
+
const icon = expanded ? (node.expandedIcon ?? node.icon) : node.icon;
|
|
70
79
|
return (
|
|
71
80
|
<>
|
|
72
|
-
{!showIcon ||
|
|
81
|
+
{!showIcon || icon === undefined ? null : (
|
|
73
82
|
<span aria-hidden="true" style={ICON_STYLE}>
|
|
74
|
-
{
|
|
83
|
+
{icon}
|
|
75
84
|
</span>
|
|
76
85
|
)}
|
|
77
86
|
<span style={LABEL_STYLE}>{node.label}</span>
|
|
@@ -221,3 +221,22 @@ test('supports folder/file indicators without duplicating supplied row icons', (
|
|
|
221
221
|
expect(markup).not.toContain('duplicate-icon');
|
|
222
222
|
expect(markup.match(/<svg/g)?.length).toBe(2);
|
|
223
223
|
});
|
|
224
|
+
|
|
225
|
+
test('renders the expanded node icon while a chevron node is open', () => {
|
|
226
|
+
const node = {
|
|
227
|
+
id: 'src',
|
|
228
|
+
label: 'src',
|
|
229
|
+
icon: <span>closed-folder</span>,
|
|
230
|
+
expandedIcon: <span>open-folder</span>,
|
|
231
|
+
children: [{ id: 'file', label: 'file.ts' }],
|
|
232
|
+
};
|
|
233
|
+
const collapsed = renderToStaticMarkup(<TreeView expansionIndicator="chevron" nodes={[node]} />);
|
|
234
|
+
const expanded = renderToStaticMarkup(
|
|
235
|
+
<TreeView expansionIndicator="chevron" defaultExpandedIds={['src']} nodes={[node]} />,
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
expect(collapsed).toContain('closed-folder');
|
|
239
|
+
expect(collapsed).not.toContain('open-folder');
|
|
240
|
+
expect(expanded).toContain('open-folder');
|
|
241
|
+
expect(expanded).not.toContain('closed-folder');
|
|
242
|
+
});
|
|
@@ -8,6 +8,7 @@ export interface TreeItemNode<TId extends string = string> {
|
|
|
8
8
|
readonly id: TId;
|
|
9
9
|
readonly label: React.ReactNode;
|
|
10
10
|
readonly icon?: React.ReactNode;
|
|
11
|
+
readonly expandedIcon?: React.ReactNode;
|
|
11
12
|
readonly children?: readonly TreeItemNode<TId>[];
|
|
12
13
|
readonly disabled?: boolean;
|
|
13
14
|
readonly meta?: React.ReactNode;
|
package/src/types/tree-view.ts
CHANGED
|
@@ -74,11 +74,12 @@ function TreeItemInner({
|
|
|
74
74
|
hasChildren
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
|
+
const nodeIcon = isExpanded ? node.expandedIcon ?? node.icon : node.icon;
|
|
77
78
|
const listItemProps = {
|
|
78
79
|
title: node.label,
|
|
79
|
-
leading: expansionIndicator === "folder" ||
|
|
80
|
-
...
|
|
81
|
-
size:
|
|
80
|
+
leading: expansionIndicator === "folder" || nodeIcon === undefined ? undefined : /* @__PURE__ */ jsx(Icon2, {
|
|
81
|
+
...nodeIcon,
|
|
82
|
+
size: 12
|
|
82
83
|
}),
|
|
83
84
|
meta: node.meta,
|
|
84
85
|
disabled: node.disabled,
|
|
@@ -4,6 +4,7 @@ export interface TreeItemNode<TId extends string = string> {
|
|
|
4
4
|
readonly id: TId;
|
|
5
5
|
readonly label: React.ReactNode;
|
|
6
6
|
readonly icon?: React.ReactNode;
|
|
7
|
+
readonly expandedIcon?: React.ReactNode;
|
|
7
8
|
readonly children?: readonly TreeItemNode<TId>[];
|
|
8
9
|
readonly disabled?: boolean;
|
|
9
10
|
readonly meta?: React.ReactNode;
|
|
@@ -53,6 +53,7 @@ function TreeItemRow(props) {
|
|
|
53
53
|
expanded,
|
|
54
54
|
hasChildren
|
|
55
55
|
}) ?? /* @__PURE__ */ jsx2(TreeItemDefaultContent, {
|
|
56
|
+
expanded,
|
|
56
57
|
node,
|
|
57
58
|
showIcon: props.expansionIndicator === "chevron"
|
|
58
59
|
});
|
|
@@ -90,15 +91,17 @@ function TreeItemRow(props) {
|
|
|
90
91
|
});
|
|
91
92
|
}
|
|
92
93
|
function TreeItemDefaultContent({
|
|
94
|
+
expanded,
|
|
93
95
|
node,
|
|
94
96
|
showIcon
|
|
95
97
|
}) {
|
|
98
|
+
const icon = expanded ? node.expandedIcon ?? node.icon : node.icon;
|
|
96
99
|
return /* @__PURE__ */ jsxs(Fragment, {
|
|
97
100
|
children: [
|
|
98
|
-
!showIcon ||
|
|
101
|
+
!showIcon || icon === undefined ? null : /* @__PURE__ */ jsx2("span", {
|
|
99
102
|
"aria-hidden": "true",
|
|
100
103
|
style: ICON_STYLE,
|
|
101
|
-
children:
|
|
104
|
+
children: icon
|
|
102
105
|
}),
|
|
103
106
|
/* @__PURE__ */ jsx2("span", {
|
|
104
107
|
style: LABEL_STYLE,
|