@mittwald/flow-react-components 1.6.0-next.45 → 1.6.0-next.46
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/dist/assets/component-index.json +1 -1
- package/dist/assets/doc-properties.json +1 -1
- package/dist/js/packages/components/src/components/List/List.mjs +27 -23
- package/dist/js/packages/components/src/components/List/List.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/Items/Items.mjs +24 -1
- package/dist/js/packages/components/src/components/List/components/Items/Items.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/ListItemView/ListItemView.mjs +46 -44
- package/dist/js/packages/components/src/components/List/components/ListItemView/ListItemView.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/components/ListItemView/components/ListItemViewContent/ListItemViewContent.mjs +25 -25
- package/dist/js/packages/components/src/components/List/components/ListItemView/components/ListItemViewContent/ListItemViewContent.mjs.map +1 -1
- package/dist/js/packages/components/src/components/List/hooks/useListSelector.mjs +18 -0
- package/dist/js/packages/components/src/components/List/hooks/useListSelector.mjs.map +1 -0
- package/dist/js/packages/components/src/components/List/listContext.mjs +32 -2
- package/dist/js/packages/components/src/components/List/listContext.mjs.map +1 -1
- package/dist/types/components/List/hooks/useListSelector.d.ts +6 -0
- package/dist/types/components/List/listContext.d.ts +16 -0
- package/package.json +10 -10
|
@@ -4,7 +4,7 @@ import { PropsContextProvider } from "../../lib/propsContext/components/PropsCon
|
|
|
4
4
|
import { flowComponent } from "../../lib/componentFactory/flowComponent.mjs";
|
|
5
5
|
import { UiComponentTunnelExit } from "../UiComponentTunnel/UiComponentTunnelExit.mjs";
|
|
6
6
|
import DivView from "../../views/DivView.mjs";
|
|
7
|
-
import { listContext } from "./listContext.mjs";
|
|
7
|
+
import { ListContextStore, listContext, listStoreContext } from "./listContext.mjs";
|
|
8
8
|
import { DataLoader } from "./components/DataLoader/DataLoader.mjs";
|
|
9
9
|
import Header_module_default from "./components/Header/Header.module.mjs";
|
|
10
10
|
import { Header } from "./components/Header/Header.mjs";
|
|
@@ -112,6 +112,7 @@ var List = flowComponent("List", (props) => {
|
|
|
112
112
|
component: "List"
|
|
113
113
|
} }
|
|
114
114
|
};
|
|
115
|
+
const listStore = ListContextStore.useNew(listModel);
|
|
115
116
|
const isEmpty = listModel.useIsEmpty();
|
|
116
117
|
const emptyView = /* @__PURE__ */ jsx(DivView, {
|
|
117
118
|
"aria-hidden": !isEmpty,
|
|
@@ -124,29 +125,32 @@ var List = flowComponent("List", (props) => {
|
|
|
124
125
|
});
|
|
125
126
|
return /* @__PURE__ */ jsx(PropsContextProvider, {
|
|
126
127
|
props: propsContext,
|
|
127
|
-
children: /* @__PURE__ */
|
|
128
|
+
children: /* @__PURE__ */ jsx(listContext.Provider, {
|
|
128
129
|
value: { list: listModel },
|
|
129
|
-
children:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
130
|
+
children: /* @__PURE__ */ jsxs(listStoreContext.Provider, {
|
|
131
|
+
value: listStore,
|
|
132
|
+
children: [/* @__PURE__ */ jsx(DataLoader, {}), /* @__PURE__ */ jsxs(DivView, {
|
|
133
|
+
className: List_module_default.list,
|
|
134
|
+
ref,
|
|
135
|
+
children: [
|
|
136
|
+
children,
|
|
137
|
+
/* @__PURE__ */ jsx(Header, {}),
|
|
138
|
+
/* @__PURE__ */ jsxs(DivView, {
|
|
139
|
+
className: List_module_default.listWrapper,
|
|
140
|
+
children: [
|
|
141
|
+
emptyView,
|
|
142
|
+
listModel.items.entries.length > 0 && /* @__PURE__ */ jsx(UiComponentTunnelExit, {
|
|
143
|
+
id: "listSummary",
|
|
144
|
+
component: "List"
|
|
145
|
+
}),
|
|
146
|
+
(listModel.viewMode.isList || listModel.viewMode.isTiles) && /* @__PURE__ */ jsx(Items, {}),
|
|
147
|
+
listModel.viewMode.isTable && /* @__PURE__ */ jsx(Table, {})
|
|
148
|
+
]
|
|
149
|
+
}),
|
|
150
|
+
!hidePagination && /* @__PURE__ */ jsx(Footer, {})
|
|
151
|
+
]
|
|
152
|
+
})]
|
|
153
|
+
})
|
|
150
154
|
})
|
|
151
155
|
});
|
|
152
156
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"List.mjs","names":["TableSetupComponent","ListModel","headerStyles","styles"],"sources":["../../../../../../../src/components/List/List.tsx"],"sourcesContent":["import { DataLoader } from \"@/components/List/components/DataLoader\";\nimport { Header } from \"@/components/List/components/Header/Header\";\nimport headerStyles from \"@/components/List/components/Header/Header.module.scss\";\nimport { Items } from \"@/components/List/components/Items/Items\";\nimport { Table } from \"@/components/List/components/Table\";\nimport ListModel from \"@/components/List/model/List\";\nimport type { IncrementalLoaderShape } from \"@/components/List/model/loading/types\";\nimport type { ListShape } from \"@/components/List/model/types\";\nimport { ListFilter } from \"@/components/List/setupComponents/ListFilter\";\nimport { ListItem } from \"@/components/List/setupComponents/ListItem\";\nimport { ListLoaderAsync } from \"@/components/List/setupComponents/ListLoaderAsync\";\nimport { ListLoaderAsyncResource } from \"@/components/List/setupComponents/ListLoaderAsyncResource\";\nimport { ListSearch } from \"@/components/List/setupComponents/ListSearch\";\nimport { ListSorting } from \"@/components/List/setupComponents/ListSorting\";\nimport { ListStaticData } from \"@/components/List/setupComponents/ListStaticData\";\nimport { Table as TableSetupComponent } from \"@/components/List/setupComponents/Table\";\nimport { TableBody } from \"@/components/List/setupComponents/TableBody\";\nimport { TableCell } from \"@/components/List/setupComponents/TableCell\";\nimport { TableColumn } from \"@/components/List/setupComponents/TableColumn\";\nimport { TableHeader } from \"@/components/List/setupComponents/TableHeader\";\nimport { TableRow } from \"@/components/List/setupComponents/TableRow\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport { type PropsContext, PropsContextProvider } from \"@/lib/propsContext\";\nimport { deepFilterByType, deepFindOfType } from \"@/lib/react/deepFindOfType\";\nimport DivView from \"@/views/DivView\";\nimport type { PropsWithChildren, ReactNode } from \"react\";\nimport Footer from \"./components/Footer\";\nimport styles from \"./List.module.scss\";\nimport { listContext } from \"./listContext\";\nimport { ListLoaderHooks } from \"@/components/List/setupComponents/ListLoaderHooks\";\nimport { UiComponentTunnelExit } from \"../UiComponentTunnel/UiComponentTunnelExit\";\nimport ListEmptyViewContainerView from \"@/views/ListEmptyViewContainerView\";\n\nexport interface ListProps<T, TMeta = unknown>\n extends\n PropsWithChildren,\n FlowComponentProps,\n Omit<\n ListShape<T, TMeta>,\n | \"search\"\n | \"loader\"\n | \"itemView\"\n | \"table\"\n | \"batchesController\"\n | \"filters\"\n | \"sorting\"\n > {\n /** The number of items to be displayed on one page. */\n batchSize?: number;\n /**\n * Automatically loads the next batch of items when the user scrolls to the\n * end of the list, instead of showing a \"Show more\" button.\n *\n * @default false\n */\n infiniteScroll?: boolean;\n /**\n * Hides the pagination controls below the list.\n *\n * @default false\n */\n hidePagination?: boolean;\n /** The view rendered when a search or filter returns no results. */\n emptySearchResultView?: ReactNode;\n /** The view rendered when the list contains no items. */\n emptyView?: ReactNode;\n}\n\nexport const List = flowComponent(\"List\", (props) => {\n const {\n children,\n batchSize,\n loadingItemsCount = batchSize,\n onChange,\n ref,\n hidePagination,\n ...restProps\n } = props;\n\n const listLoaderAsync = deepFindOfType(\n children,\n ListLoaderAsync<never>,\n )?.props;\n const listLoaderHooks = deepFindOfType(\n children,\n ListLoaderHooks<never>,\n )?.props;\n const listLoaderAsyncResource = deepFindOfType(\n children,\n ListLoaderAsyncResource<never>,\n )?.props;\n const listStaticData = deepFindOfType(children, ListStaticData<never>)?.props;\n\n const loaderShape: IncrementalLoaderShape<never> = {\n source: listLoaderAsync\n ? {\n ...listLoaderAsync,\n asyncLoader: listLoaderAsync.children,\n }\n : listLoaderAsyncResource\n ? {\n ...listLoaderAsyncResource,\n asyncResourceFactory: listLoaderAsyncResource.children,\n }\n : listStaticData\n ? {\n staticData: listStaticData.data,\n }\n : listLoaderHooks\n ? {\n ...listLoaderHooks,\n useData: listLoaderHooks.children,\n }\n : undefined,\n };\n\n const searchProps = deepFindOfType(children, ListSearch)?.props;\n const itemViewProps = deepFindOfType(children, ListItem<never>)?.props;\n\n const tableProps = deepFindOfType(children, TableSetupComponent)?.props;\n const tableColumnProps = deepFilterByType(children, TableColumn<never>).map(\n (c) => ({\n ...c.props,\n name: c.props.children,\n }),\n );\n const tableCellProps = deepFilterByType(children, TableCell<never>).map(\n (c) => ({\n ...c.props,\n renderFn: c.props.children,\n }),\n );\n\n const tableRowProps = deepFindOfType(children, TableRow)?.props;\n const tableHeaderProps = deepFindOfType(children, TableHeader)?.props;\n const tableBodyProps = deepFindOfType(children, TableBody)?.props;\n\n const listModel = ListModel.useNew<never>({\n onChange,\n loader: loaderShape,\n filters: deepFilterByType(children, ListFilter<never, never, never>).map(\n (f) => ({\n ...f.props,\n renderItem: f.props.children,\n }),\n ),\n search: searchProps\n ? {\n render: searchProps.children,\n textFieldProps: searchProps,\n defaultValue: searchProps.defaultValue,\n autosave: searchProps.autosave,\n }\n : undefined,\n sorting: deepFilterByType(children, ListSorting<never>).map((s) => s.props),\n\n itemView: itemViewProps\n ? {\n ...itemViewProps,\n renderFn: itemViewProps.children,\n }\n : undefined,\n\n table:\n tableColumnProps.length > 0\n ? {\n header: {\n ...tableHeaderProps,\n columns: tableColumnProps,\n },\n body: {\n ...tableBodyProps,\n row: {\n ...tableRowProps,\n cells: tableCellProps,\n },\n },\n ...tableProps,\n }\n : undefined,\n\n batchesController: {\n batchSize,\n },\n loadingItemsCount,\n ...restProps,\n });\n\n const propsContext: PropsContext = {\n ActionGroup: {\n preserveOrder: true,\n tunnel: {\n id: \"actions\",\n component: \"List\",\n },\n className: headerStyles.actions,\n Button: {\n className: headerStyles.action,\n },\n },\n ListSummary: {\n tunnel: {\n id: \"listSummary\",\n component: \"List\",\n },\n },\n };\n\n const isEmpty = listModel.useIsEmpty();\n\n // IMPORTANT: we always render the emptyView to the dom.\n // otherwise we will lose e.g. modalState when switching from noItems to itemsAvailable and vise versa.\n const emptyView = (\n <DivView\n aria-hidden={!isEmpty}\n className={!isEmpty ? styles.hideVisuallyEmptyView : undefined}\n >\n <ListEmptyViewContainerView\n viewType={listModel.getEmptyViewType()}\n emptySearchResultView={listModel.emptySearchResultView}\n emptyView={listModel.emptyView}\n />\n </DivView>\n );\n\n return (\n <PropsContextProvider props={propsContext}>\n <listContext.Provider\n value={{\n list: listModel,\n }}\n >\n <DataLoader />\n <DivView className={styles.list} ref={ref}>\n {children}\n <Header />\n\n <DivView className={styles.listWrapper}>\n {emptyView}\n {listModel.items.entries.length > 0 && (\n <UiComponentTunnelExit id=\"listSummary\" component=\"List\" />\n )}\n {(listModel.viewMode.isList || listModel.viewMode.isTiles) && (\n <Items />\n )}\n {listModel.viewMode.isTable && <Table />}\n </DivView>\n {!hidePagination && <Footer />}\n </DivView>\n </listContext.Provider>\n </PropsContextProvider>\n );\n});\n\nexport default List;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"List.mjs","names":["TableSetupComponent","ListModel","headerStyles","styles"],"sources":["../../../../../../../src/components/List/List.tsx"],"sourcesContent":["import { DataLoader } from \"@/components/List/components/DataLoader\";\nimport { Header } from \"@/components/List/components/Header/Header\";\nimport headerStyles from \"@/components/List/components/Header/Header.module.scss\";\nimport { Items } from \"@/components/List/components/Items/Items\";\nimport { Table } from \"@/components/List/components/Table\";\nimport ListModel from \"@/components/List/model/List\";\nimport type { IncrementalLoaderShape } from \"@/components/List/model/loading/types\";\nimport type { ListShape } from \"@/components/List/model/types\";\nimport { ListFilter } from \"@/components/List/setupComponents/ListFilter\";\nimport { ListItem } from \"@/components/List/setupComponents/ListItem\";\nimport { ListLoaderAsync } from \"@/components/List/setupComponents/ListLoaderAsync\";\nimport { ListLoaderAsyncResource } from \"@/components/List/setupComponents/ListLoaderAsyncResource\";\nimport { ListSearch } from \"@/components/List/setupComponents/ListSearch\";\nimport { ListSorting } from \"@/components/List/setupComponents/ListSorting\";\nimport { ListStaticData } from \"@/components/List/setupComponents/ListStaticData\";\nimport { Table as TableSetupComponent } from \"@/components/List/setupComponents/Table\";\nimport { TableBody } from \"@/components/List/setupComponents/TableBody\";\nimport { TableCell } from \"@/components/List/setupComponents/TableCell\";\nimport { TableColumn } from \"@/components/List/setupComponents/TableColumn\";\nimport { TableHeader } from \"@/components/List/setupComponents/TableHeader\";\nimport { TableRow } from \"@/components/List/setupComponents/TableRow\";\nimport {\n flowComponent,\n type FlowComponentProps,\n} from \"@/lib/componentFactory/flowComponent\";\nimport { type PropsContext, PropsContextProvider } from \"@/lib/propsContext\";\nimport { deepFilterByType, deepFindOfType } from \"@/lib/react/deepFindOfType\";\nimport DivView from \"@/views/DivView\";\nimport type { PropsWithChildren, ReactNode } from \"react\";\nimport Footer from \"./components/Footer\";\nimport styles from \"./List.module.scss\";\nimport { listContext, ListContextStore, listStoreContext } from \"./listContext\";\nimport { ListLoaderHooks } from \"@/components/List/setupComponents/ListLoaderHooks\";\nimport { UiComponentTunnelExit } from \"../UiComponentTunnel/UiComponentTunnelExit\";\nimport ListEmptyViewContainerView from \"@/views/ListEmptyViewContainerView\";\n\nexport interface ListProps<T, TMeta = unknown>\n extends\n PropsWithChildren,\n FlowComponentProps,\n Omit<\n ListShape<T, TMeta>,\n | \"search\"\n | \"loader\"\n | \"itemView\"\n | \"table\"\n | \"batchesController\"\n | \"filters\"\n | \"sorting\"\n > {\n /** The number of items to be displayed on one page. */\n batchSize?: number;\n /**\n * Automatically loads the next batch of items when the user scrolls to the\n * end of the list, instead of showing a \"Show more\" button.\n *\n * @default false\n */\n infiniteScroll?: boolean;\n /**\n * Hides the pagination controls below the list.\n *\n * @default false\n */\n hidePagination?: boolean;\n /** The view rendered when a search or filter returns no results. */\n emptySearchResultView?: ReactNode;\n /** The view rendered when the list contains no items. */\n emptyView?: ReactNode;\n}\n\nexport const List = flowComponent(\"List\", (props) => {\n const {\n children,\n batchSize,\n loadingItemsCount = batchSize,\n onChange,\n ref,\n hidePagination,\n ...restProps\n } = props;\n\n const listLoaderAsync = deepFindOfType(\n children,\n ListLoaderAsync<never>,\n )?.props;\n const listLoaderHooks = deepFindOfType(\n children,\n ListLoaderHooks<never>,\n )?.props;\n const listLoaderAsyncResource = deepFindOfType(\n children,\n ListLoaderAsyncResource<never>,\n )?.props;\n const listStaticData = deepFindOfType(children, ListStaticData<never>)?.props;\n\n const loaderShape: IncrementalLoaderShape<never> = {\n source: listLoaderAsync\n ? {\n ...listLoaderAsync,\n asyncLoader: listLoaderAsync.children,\n }\n : listLoaderAsyncResource\n ? {\n ...listLoaderAsyncResource,\n asyncResourceFactory: listLoaderAsyncResource.children,\n }\n : listStaticData\n ? {\n staticData: listStaticData.data,\n }\n : listLoaderHooks\n ? {\n ...listLoaderHooks,\n useData: listLoaderHooks.children,\n }\n : undefined,\n };\n\n const searchProps = deepFindOfType(children, ListSearch)?.props;\n const itemViewProps = deepFindOfType(children, ListItem<never>)?.props;\n\n const tableProps = deepFindOfType(children, TableSetupComponent)?.props;\n const tableColumnProps = deepFilterByType(children, TableColumn<never>).map(\n (c) => ({\n ...c.props,\n name: c.props.children,\n }),\n );\n const tableCellProps = deepFilterByType(children, TableCell<never>).map(\n (c) => ({\n ...c.props,\n renderFn: c.props.children,\n }),\n );\n\n const tableRowProps = deepFindOfType(children, TableRow)?.props;\n const tableHeaderProps = deepFindOfType(children, TableHeader)?.props;\n const tableBodyProps = deepFindOfType(children, TableBody)?.props;\n\n const listModel = ListModel.useNew<never>({\n onChange,\n loader: loaderShape,\n filters: deepFilterByType(children, ListFilter<never, never, never>).map(\n (f) => ({\n ...f.props,\n renderItem: f.props.children,\n }),\n ),\n search: searchProps\n ? {\n render: searchProps.children,\n textFieldProps: searchProps,\n defaultValue: searchProps.defaultValue,\n autosave: searchProps.autosave,\n }\n : undefined,\n sorting: deepFilterByType(children, ListSorting<never>).map((s) => s.props),\n\n itemView: itemViewProps\n ? {\n ...itemViewProps,\n renderFn: itemViewProps.children,\n }\n : undefined,\n\n table:\n tableColumnProps.length > 0\n ? {\n header: {\n ...tableHeaderProps,\n columns: tableColumnProps,\n },\n body: {\n ...tableBodyProps,\n row: {\n ...tableRowProps,\n cells: tableCellProps,\n },\n },\n ...tableProps,\n }\n : undefined,\n\n batchesController: {\n batchSize,\n },\n loadingItemsCount,\n ...restProps,\n });\n\n const propsContext: PropsContext = {\n ActionGroup: {\n preserveOrder: true,\n tunnel: {\n id: \"actions\",\n component: \"List\",\n },\n className: headerStyles.actions,\n Button: {\n className: headerStyles.action,\n },\n },\n ListSummary: {\n tunnel: {\n id: \"listSummary\",\n component: \"List\",\n },\n },\n };\n\n const listStore = ListContextStore.useNew(listModel);\n\n const isEmpty = listModel.useIsEmpty();\n\n // IMPORTANT: we always render the emptyView to the dom.\n // otherwise we will lose e.g. modalState when switching from noItems to itemsAvailable and vise versa.\n const emptyView = (\n <DivView\n aria-hidden={!isEmpty}\n className={!isEmpty ? styles.hideVisuallyEmptyView : undefined}\n >\n <ListEmptyViewContainerView\n viewType={listModel.getEmptyViewType()}\n emptySearchResultView={listModel.emptySearchResultView}\n emptyView={listModel.emptyView}\n />\n </DivView>\n );\n\n return (\n <PropsContextProvider props={propsContext}>\n <listContext.Provider\n value={{\n list: listModel,\n }}\n >\n <listStoreContext.Provider value={listStore}>\n <DataLoader />\n <DivView className={styles.list} ref={ref}>\n {children}\n <Header />\n\n <DivView className={styles.listWrapper}>\n {emptyView}\n {listModel.items.entries.length > 0 && (\n <UiComponentTunnelExit id=\"listSummary\" component=\"List\" />\n )}\n {(listModel.viewMode.isList || listModel.viewMode.isTiles) && (\n <Items />\n )}\n {listModel.viewMode.isTable && <Table />}\n </DivView>\n {!hidePagination && <Footer />}\n </DivView>\n </listStoreContext.Provider>\n </listContext.Provider>\n </PropsContextProvider>\n );\n});\n\nexport default List;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuEA,IAAa,OAAO,cAAc,SAAS,UAAU;CACnD,MAAM,EACJ,UACA,WACA,oBAAoB,WACpB,UACA,KACA,gBACA,GAAG,cACD;CAEJ,MAAM,kBAAkB,eACtB,UACA,eACF,CAAC,EAAE;CACH,MAAM,kBAAkB,eACtB,UACA,eACF,CAAC,EAAE;CACH,MAAM,0BAA0B,eAC9B,UACA,uBACF,CAAC,EAAE;CACH,MAAM,iBAAiB,eAAe,UAAU,cAAqB,CAAC,EAAE;CAExE,MAAM,cAA6C,EACjD,QAAQ,kBACJ;EACE,GAAG;EACH,aAAa,gBAAgB;CAC/B,IACA,0BACE;EACE,GAAG;EACH,sBAAsB,wBAAwB;CAChD,IACA,iBACE,EACE,YAAY,eAAe,KAC7B,IACA,kBACE;EACE,GAAG;EACH,SAAS,gBAAgB;CAC3B,IACA,KAAA,EACZ;CAEA,MAAM,cAAc,eAAe,UAAU,UAAU,CAAC,EAAE;CAC1D,MAAM,gBAAgB,eAAe,UAAU,QAAe,CAAC,EAAE;CAEjE,MAAM,aAAa,eAAe,UAAUA,OAAmB,CAAC,EAAE;CAClE,MAAM,mBAAmB,iBAAiB,UAAU,WAAkB,CAAC,CAAC,KACrE,OAAO;EACN,GAAG,EAAE;EACL,MAAM,EAAE,MAAM;CAChB,EACF;CACA,MAAM,iBAAiB,iBAAiB,UAAU,SAAgB,CAAC,CAAC,KACjE,OAAO;EACN,GAAG,EAAE;EACL,UAAU,EAAE,MAAM;CACpB,EACF;CAEA,MAAM,gBAAgB,eAAe,UAAU,QAAQ,CAAC,EAAE;CAC1D,MAAM,mBAAmB,eAAe,UAAU,WAAW,CAAC,EAAE;CAChE,MAAM,iBAAiB,eAAe,UAAU,SAAS,CAAC,EAAE;CAE5D,MAAM,YAAYC,OAAU,OAAc;EACxC;EACA,QAAQ;EACR,SAAS,iBAAiB,UAAU,UAA+B,CAAC,CAAC,KAClE,OAAO;GACN,GAAG,EAAE;GACL,YAAY,EAAE,MAAM;EACtB,EACF;EACA,QAAQ,cACJ;GACE,QAAQ,YAAY;GACpB,gBAAgB;GAChB,cAAc,YAAY;GAC1B,UAAU,YAAY;EACxB,IACA,KAAA;EACJ,SAAS,iBAAiB,UAAU,WAAkB,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK;EAE1E,UAAU,gBACN;GACE,GAAG;GACH,UAAU,cAAc;EAC1B,IACA,KAAA;EAEJ,OACE,iBAAiB,SAAS,IACtB;GACE,QAAQ;IACN,GAAG;IACH,SAAS;GACX;GACA,MAAM;IACJ,GAAG;IACH,KAAK;KACH,GAAG;KACH,OAAO;IACT;GACF;GACA,GAAG;EACL,IACA,KAAA;EAEN,mBAAmB,EACjB,UACF;EACA;EACA,GAAG;CACL,CAAC;CAED,MAAM,eAA6B;EACjC,aAAa;GACX,eAAe;GACf,QAAQ;IACN,IAAI;IACJ,WAAW;GACb;GACA,WAAWC,sBAAa;GACxB,QAAQ,EACN,WAAWA,sBAAa,OAC1B;EACF;EACA,aAAa,EACX,QAAQ;GACN,IAAI;GACJ,WAAW;EACb,EACF;CACF;CAEA,MAAM,YAAY,iBAAiB,OAAO,SAAS;CAEnD,MAAM,UAAU,UAAU,WAAW;CAIrC,MAAM,YACJ,oBAAC,SAAD;EACE,eAAa,CAAC;EACd,WAAW,CAAC,UAAUC,oBAAO,wBAAwB,KAAA;EAErD,UAAA,oBAAC,4BAAD;GACE,UAAU,UAAU,iBAAiB;GACrC,uBAAuB,UAAU;GACjC,WAAW,UAAU;EACtB,CAAA;CACM,CAAA;CAGX,OACE,oBAAC,sBAAD;EAAsB,OAAO;EAC3B,UAAA,oBAAC,YAAY,UAAb;GACE,OAAO,EACL,MAAM,UACR;GAEA,UAAA,qBAAC,iBAAiB,UAAlB;IAA2B,OAAO;IAAlC,UAAA,CACE,oBAAC,YAAD,CAAa,CAAA,GACb,qBAAC,SAAD;KAAS,WAAWA,oBAAO;KAAW;KAAtC,UAAA;MACG;MACD,oBAAC,QAAD,CAAS,CAAA;MAET,qBAAC,SAAD;OAAS,WAAWA,oBAAO;OAA3B,UAAA;QACG;QACA,UAAU,MAAM,QAAQ,SAAS,KAChC,oBAAC,uBAAD;SAAuB,IAAG;SAAc,WAAU;QAAQ,CAAA;SAE1D,UAAU,SAAS,UAAU,UAAU,SAAS,YAChD,oBAAC,OAAD,CAAQ,CAAA;QAET,UAAU,SAAS,WAAW,oBAAC,OAAD,CAAQ,CAAA;OAChC;;MACR,CAAC,kBAAkB,oBAAC,QAAD,CAAS,CAAA;KACtB;IACgB,CAAA,CAAA;;EACP,CAAA;CACF,CAAA;AAE1B,CAAC"}
|
|
@@ -9,10 +9,13 @@ import { FallbackItems } from "./components/FallbackItems/FallbackItems.mjs";
|
|
|
9
9
|
import { useInfiniteScrollTrigger } from "../../hooks/useInfiniteScrollTrigger.mjs";
|
|
10
10
|
import { useLatestOnAction } from "../../hooks/useLatestOnAction.mjs";
|
|
11
11
|
import clsx from "clsx";
|
|
12
|
+
import { useRef } from "react";
|
|
12
13
|
import { jsx } from "react/jsx-runtime";
|
|
14
|
+
import { isShallowEqual } from "remeda";
|
|
13
15
|
//#region src/components/List/components/Items/Items.tsx
|
|
14
16
|
var Items = () => {
|
|
15
17
|
const list = useList();
|
|
18
|
+
const lastRender = useRef(null);
|
|
16
19
|
const tiles = list.viewMode.isTiles;
|
|
17
20
|
const isLoading = list.loader.useIsLoading();
|
|
18
21
|
const isInitiallyLoading = list.loader.useIsInitiallyLoading();
|
|
@@ -20,6 +23,20 @@ var Items = () => {
|
|
|
20
23
|
const { triggerRef, triggerIndex } = useInfiniteScrollTrigger();
|
|
21
24
|
const onAction = useLatestOnAction(list);
|
|
22
25
|
if (!list.itemView) return null;
|
|
26
|
+
const inputs = [
|
|
27
|
+
tiles,
|
|
28
|
+
isLoading,
|
|
29
|
+
isInitiallyLoading,
|
|
30
|
+
isLoadingMore,
|
|
31
|
+
onAction,
|
|
32
|
+
triggerIndex,
|
|
33
|
+
triggerRef,
|
|
34
|
+
list.accordion,
|
|
35
|
+
list.itemView.tileMaxWidth,
|
|
36
|
+
...list.items.entries.flatMap((item) => [item.id, item.data])
|
|
37
|
+
];
|
|
38
|
+
const last = lastRender.current;
|
|
39
|
+
if (last && isShallowEqual(last.inputs, inputs) && isShallowEqual(last.list.componentProps, list.componentProps) && list.items.entries.every((item) => !!last.list.itemView?.rendersSameFor(list.itemView, item.data))) return last.element;
|
|
23
40
|
const items = list.items.entries.map((item, index) => /* @__PURE__ */ jsx(Item, {
|
|
24
41
|
data: item.data,
|
|
25
42
|
id: item.id,
|
|
@@ -30,7 +47,7 @@ var Items = () => {
|
|
|
30
47
|
}, item.id));
|
|
31
48
|
const rootClassName = clsx(Items_module_default.items, isLoading && !(list.infiniteScroll && isLoadingMore) && Items_module_default.isLoading, tiles && Items_module_default.tiles);
|
|
32
49
|
const { "aria-labelledby": ariaLabelledby, "aria-label": ariaLabel, ...rest } = list.componentProps;
|
|
33
|
-
|
|
50
|
+
const element = /* @__PURE__ */ jsx(DivView, {
|
|
34
51
|
"aria-hidden": isInitiallyLoading,
|
|
35
52
|
"aria-busy": isLoading,
|
|
36
53
|
children: /* @__PURE__ */ jsx(ItemsGridListView, {
|
|
@@ -43,6 +60,12 @@ var Items = () => {
|
|
|
43
60
|
children: items.length === 0 && isInitiallyLoading ? /* @__PURE__ */ jsx(FallbackItems, {}) : items
|
|
44
61
|
})
|
|
45
62
|
});
|
|
63
|
+
lastRender.current = {
|
|
64
|
+
inputs,
|
|
65
|
+
list,
|
|
66
|
+
element
|
|
67
|
+
};
|
|
68
|
+
return element;
|
|
46
69
|
};
|
|
47
70
|
//#endregion
|
|
48
71
|
export { Items, Items as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Items.mjs","names":["styles"],"sources":["../../../../../../../../../src/components/List/components/Items/Items.tsx"],"sourcesContent":["import Item from \"@/components/List/components/Items/components/Item/Item\";\nimport { useList } from \"@/components/List/hooks/useList\";\nimport DivView from \"@/views/DivView\";\nimport ItemsGridListView from \"@/views/ItemsGridListView\";\nimport clsx from \"clsx\";\nimport type { FC } from \"react\";\nimport styles from \"./Items.module.scss\";\nimport { FallbackItems } from \"./components/FallbackItems\";\nimport { useInfiniteScrollTrigger } from \"@/components/List/hooks/useInfiniteScrollTrigger\";\nimport { useLatestOnAction } from \"@/components/List/hooks/useLatestOnAction\";\n\nexport const Items: FC = () => {\n const list = useList();\n const tiles = list.viewMode.isTiles;\n const isLoading = list.loader.useIsLoading();\n const isInitiallyLoading = list.loader.useIsInitiallyLoading();\n const isLoadingMore = list.loader.useIsLoadingMore();\n\n const { triggerRef, triggerIndex } = useInfiniteScrollTrigger();\n\n const onAction = useLatestOnAction(list);\n\n if (!list.itemView) {\n return null;\n }\n\n const items = list.items.entries.map((item, index) => (\n <Item\n key={item.id}\n data={item.data}\n id={item.id}\n list={list}\n onAction={onAction}\n isTile={tiles}\n triggerRef={index === triggerIndex ? triggerRef : undefined}\n />\n ));\n\n const rootClassName = clsx(\n styles.items,\n isLoading && !(list.infiniteScroll && isLoadingMore) && styles.isLoading,\n tiles && styles.tiles,\n );\n\n const {\n \"aria-labelledby\": ariaLabelledby,\n \"aria-label\": ariaLabel,\n ...rest\n } = list.componentProps;\n\n
|
|
1
|
+
{"version":3,"file":"Items.mjs","names":["styles"],"sources":["../../../../../../../../../src/components/List/components/Items/Items.tsx"],"sourcesContent":["import Item from \"@/components/List/components/Items/components/Item/Item\";\nimport { useList } from \"@/components/List/hooks/useList\";\nimport DivView from \"@/views/DivView\";\nimport ItemsGridListView from \"@/views/ItemsGridListView\";\nimport clsx from \"clsx\";\nimport type { FC, ReactElement } from \"react\";\nimport { useRef } from \"react\";\nimport { isShallowEqual } from \"remeda\";\nimport type List from \"@/components/List/model/List\";\nimport styles from \"./Items.module.scss\";\nimport { FallbackItems } from \"./components/FallbackItems\";\nimport { useInfiniteScrollTrigger } from \"@/components/List/hooks/useInfiniteScrollTrigger\";\nimport { useLatestOnAction } from \"@/components/List/hooks/useLatestOnAction\";\n\ninterface LastRender {\n inputs: unknown[];\n list: List<never>;\n element: ReactElement;\n}\n\nexport const Items: FC = () => {\n const list = useList();\n const lastRender = useRef<LastRender | null>(null);\n const tiles = list.viewMode.isTiles;\n const isLoading = list.loader.useIsLoading();\n const isInitiallyLoading = list.loader.useIsInitiallyLoading();\n const isLoadingMore = list.loader.useIsLoadingMore();\n\n const { triggerRef, triggerIndex } = useInfiniteScrollTrigger();\n\n const onAction = useLatestOnAction(list);\n\n if (!list.itemView) {\n return null;\n }\n\n /*\n * react-aria re-renders every item whenever its GridList renders, Flow's\n * item memo or not. While nothing the items show has changed, the GridList\n * gets the element of the last render, so it does not render at all. Items\n * count as unchanged by the same rule as the item memo.\n */\n const inputs = [\n tiles,\n isLoading,\n isInitiallyLoading,\n isLoadingMore,\n onAction,\n triggerIndex,\n triggerRef,\n list.accordion,\n list.itemView.tileMaxWidth,\n ...list.items.entries.flatMap((item) => [item.id, item.data]),\n ];\n const last = lastRender.current;\n if (\n last &&\n isShallowEqual(last.inputs, inputs) &&\n isShallowEqual(last.list.componentProps, list.componentProps) &&\n list.items.entries.every(\n (item) => !!last.list.itemView?.rendersSameFor(list.itemView, item.data),\n )\n ) {\n return last.element;\n }\n\n const items = list.items.entries.map((item, index) => (\n <Item\n key={item.id}\n data={item.data}\n id={item.id}\n list={list}\n onAction={onAction}\n isTile={tiles}\n triggerRef={index === triggerIndex ? triggerRef : undefined}\n />\n ));\n\n const rootClassName = clsx(\n styles.items,\n isLoading && !(list.infiniteScroll && isLoadingMore) && styles.isLoading,\n tiles && styles.tiles,\n );\n\n const {\n \"aria-labelledby\": ariaLabelledby,\n \"aria-label\": ariaLabel,\n ...rest\n } = list.componentProps;\n\n const element = (\n <DivView aria-hidden={isInitiallyLoading} aria-busy={isLoading}>\n <ItemsGridListView\n className={rootClassName}\n {...rest}\n aria-labelledby={ariaLabel ? undefined : ariaLabelledby}\n aria-label={ariaLabel}\n layout={tiles ? \"grid\" : \"stack\"}\n tileMaxWidth={list.itemView.tileMaxWidth}\n >\n {items.length === 0 && isInitiallyLoading ? <FallbackItems /> : items}\n </ItemsGridListView>\n </DivView>\n );\n lastRender.current = { inputs, list, element };\n return element;\n};\n\nexport default Items;\n"],"mappings":";;;;;;;;;;;;;;;AAoBA,IAAa,cAAkB;CAC7B,MAAM,OAAO,QAAQ;CACrB,MAAM,aAAa,OAA0B,IAAI;CACjD,MAAM,QAAQ,KAAK,SAAS;CAC5B,MAAM,YAAY,KAAK,OAAO,aAAa;CAC3C,MAAM,qBAAqB,KAAK,OAAO,sBAAsB;CAC7D,MAAM,gBAAgB,KAAK,OAAO,iBAAiB;CAEnD,MAAM,EAAE,YAAY,iBAAiB,yBAAyB;CAE9D,MAAM,WAAW,kBAAkB,IAAI;CAEvC,IAAI,CAAC,KAAK,UACR,OAAO;CAST,MAAM,SAAS;EACb;EACA;EACA;EACA;EACA;EACA;EACA;EACA,KAAK;EACL,KAAK,SAAS;EACd,GAAG,KAAK,MAAM,QAAQ,SAAS,SAAS,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC;CAC9D;CACA,MAAM,OAAO,WAAW;CACxB,IACE,QACA,eAAe,KAAK,QAAQ,MAAM,KAClC,eAAe,KAAK,KAAK,gBAAgB,KAAK,cAAc,KAC5D,KAAK,MAAM,QAAQ,OAChB,SAAS,CAAC,CAAC,KAAK,KAAK,UAAU,eAAe,KAAK,UAAU,KAAK,IAAI,CACzE,GAEA,OAAO,KAAK;CAGd,MAAM,QAAQ,KAAK,MAAM,QAAQ,KAAK,MAAM,UAC1C,oBAAC,MAAD;EAEE,MAAM,KAAK;EACX,IAAI,KAAK;EACH;EACI;EACV,QAAQ;EACR,YAAY,UAAU,eAAe,aAAa,KAAA;CACnD,GAPM,KAAK,EAOX,CACF;CAED,MAAM,gBAAgB,KACpBA,qBAAO,OACP,aAAa,EAAE,KAAK,kBAAkB,kBAAkBA,qBAAO,WAC/D,SAASA,qBAAO,KAClB;CAEA,MAAM,EACJ,mBAAmB,gBACnB,cAAc,WACd,GAAG,SACD,KAAK;CAET,MAAM,UACJ,oBAAC,SAAD;EAAS,eAAa;EAAoB,aAAW;EACnD,UAAA,oBAAC,mBAAD;GACE,WAAW;GACX,GAAI;GACJ,mBAAiB,YAAY,KAAA,IAAY;GACzC,cAAY;GACZ,QAAQ,QAAQ,SAAS;GACzB,cAAc,KAAK,SAAS;GAE3B,UAAA,MAAM,WAAW,KAAK,qBAAqB,oBAAC,eAAD,CAAgB,CAAA,IAAI;EAC/C,CAAA;CACZ,CAAA;CAEX,WAAW,UAAU;EAAE;EAAQ;EAAM;CAAQ;CAC7C,OAAO;AACT"}
|
package/dist/js/packages/components/src/components/List/components/ListItemView/ListItemView.mjs
CHANGED
|
@@ -8,54 +8,56 @@ import { UiComponentTunnelExit } from "../../../UiComponentTunnel/UiComponentTun
|
|
|
8
8
|
import { OptionsButton } from "../Items/components/Item/components/OptionsButton/OptionsButton.mjs";
|
|
9
9
|
import ListItemView_module_default from "./ListItemView.module.mjs";
|
|
10
10
|
import ListItemViewContentView from "../../../../views/ListItemViewContentView.mjs";
|
|
11
|
-
import {
|
|
11
|
+
import { useListSelector } from "../../hooks/useListSelector.mjs";
|
|
12
12
|
import { jsx } from "react/jsx-runtime";
|
|
13
13
|
//#region src/components/List/components/ListItemView/ListItemView.tsx
|
|
14
|
+
var buttonTunnel = {
|
|
15
|
+
id: "button",
|
|
16
|
+
component: "ListItemView"
|
|
17
|
+
};
|
|
18
|
+
var buildPropsContext = (buttonSize) => ({
|
|
19
|
+
...overlayTriggersTunneledTo(buttonTunnel),
|
|
20
|
+
ContextMenu: {
|
|
21
|
+
tunnel: buttonTunnel,
|
|
22
|
+
placement: "bottom right",
|
|
23
|
+
wrapWith: /* @__PURE__ */ jsx(OptionsButton, { className: ListItemView_module_default.action })
|
|
24
|
+
},
|
|
25
|
+
Button: {
|
|
26
|
+
tunnel: buttonTunnel,
|
|
27
|
+
size: buttonSize
|
|
28
|
+
},
|
|
29
|
+
ActionGroup: {
|
|
30
|
+
tunnel: buttonTunnel,
|
|
31
|
+
Button: { tunnel: null }
|
|
32
|
+
},
|
|
33
|
+
Avatar: { tunnel: {
|
|
34
|
+
id: "avatar",
|
|
35
|
+
component: "ListItemView"
|
|
36
|
+
} },
|
|
37
|
+
Heading: { tunnel: {
|
|
38
|
+
id: "title",
|
|
39
|
+
component: "ListItemView"
|
|
40
|
+
} },
|
|
41
|
+
Text: { tunnel: {
|
|
42
|
+
id: "text",
|
|
43
|
+
component: "ListItemView"
|
|
44
|
+
} },
|
|
45
|
+
Content: { tunnel: dynamic((p) => p.slot === "bottom" ? {
|
|
46
|
+
id: "bottom",
|
|
47
|
+
component: "ListItemView"
|
|
48
|
+
} : void 0) },
|
|
49
|
+
Checkbox: { tunnel: {
|
|
50
|
+
id: "checkbox",
|
|
51
|
+
component: "ListItemView"
|
|
52
|
+
} }
|
|
53
|
+
});
|
|
54
|
+
var listPropsContext = buildPropsContext("m");
|
|
55
|
+
var tilesPropsContext = buildPropsContext("s");
|
|
14
56
|
var ListItemView = flowComponent("ListItemView", (props) => {
|
|
15
57
|
const { children, s, m, l } = props;
|
|
16
|
-
const
|
|
17
|
-
const buttonTunnel = {
|
|
18
|
-
id: "button",
|
|
19
|
-
component: "ListItemView"
|
|
20
|
-
};
|
|
21
|
-
const propsContext = {
|
|
22
|
-
...overlayTriggersTunneledTo(buttonTunnel),
|
|
23
|
-
ContextMenu: {
|
|
24
|
-
tunnel: buttonTunnel,
|
|
25
|
-
placement: "bottom right",
|
|
26
|
-
wrapWith: /* @__PURE__ */ jsx(OptionsButton, { className: ListItemView_module_default.action })
|
|
27
|
-
},
|
|
28
|
-
Button: {
|
|
29
|
-
tunnel: buttonTunnel,
|
|
30
|
-
size: dynamic(() => useList().viewMode.isTiles ? "s" : "m")
|
|
31
|
-
},
|
|
32
|
-
ActionGroup: {
|
|
33
|
-
tunnel: buttonTunnel,
|
|
34
|
-
Button: { tunnel: null }
|
|
35
|
-
},
|
|
36
|
-
Avatar: { tunnel: {
|
|
37
|
-
id: "avatar",
|
|
38
|
-
component: "ListItemView"
|
|
39
|
-
} },
|
|
40
|
-
Heading: { tunnel: {
|
|
41
|
-
id: "title",
|
|
42
|
-
component: "ListItemView"
|
|
43
|
-
} },
|
|
44
|
-
Text: { tunnel: {
|
|
45
|
-
id: "text",
|
|
46
|
-
component: "ListItemView"
|
|
47
|
-
} },
|
|
48
|
-
Content: { tunnel: dynamic((p) => p.slot === "bottom" ? {
|
|
49
|
-
id: "bottom",
|
|
50
|
-
component: "ListItemView"
|
|
51
|
-
} : void 0) },
|
|
52
|
-
Checkbox: { tunnel: {
|
|
53
|
-
id: "checkbox",
|
|
54
|
-
component: "ListItemView"
|
|
55
|
-
} }
|
|
56
|
-
};
|
|
58
|
+
const viewMode = useListSelector((list) => list.viewMode.value);
|
|
57
59
|
return /* @__PURE__ */ jsx(ListItemViewContentView, {
|
|
58
|
-
viewMode
|
|
60
|
+
viewMode,
|
|
59
61
|
title: /* @__PURE__ */ jsx(UiComponentTunnelExit, {
|
|
60
62
|
id: "title",
|
|
61
63
|
component: "ListItemView"
|
|
@@ -84,7 +86,7 @@ var ListItemView = flowComponent("ListItemView", (props) => {
|
|
|
84
86
|
m,
|
|
85
87
|
l,
|
|
86
88
|
children: /* @__PURE__ */ jsx(PropsContextProvider, {
|
|
87
|
-
props:
|
|
89
|
+
props: viewMode === "tiles" ? tilesPropsContext : listPropsContext,
|
|
88
90
|
children
|
|
89
91
|
})
|
|
90
92
|
});
|
package/dist/js/packages/components/src/components/List/components/ListItemView/ListItemView.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListItemView.mjs","names":["styles"],"sources":["../../../../../../../../../src/components/List/components/ListItemView/ListItemView.tsx"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport styles from \"./ListItemView.module.scss\";\nimport ListItemViewContentView from \"@/views/ListItemViewContentView\";\nimport {\n dynamic,\n overlayTriggersTunneledTo,\n type PropsContext,\n PropsContextProvider,\n} from \"@/lib/propsContext\";\nimport { OptionsButton } from \"@/components/List/components/Items/components/Item/components/OptionsButton\";\nimport {
|
|
1
|
+
{"version":3,"file":"ListItemView.mjs","names":["styles"],"sources":["../../../../../../../../../src/components/List/components/ListItemView/ListItemView.tsx"],"sourcesContent":["import type { PropsWithChildren } from \"react\";\nimport styles from \"./ListItemView.module.scss\";\nimport ListItemViewContentView from \"@/views/ListItemViewContentView\";\nimport {\n dynamic,\n overlayTriggersTunneledTo,\n type PropsContext,\n PropsContextProvider,\n} from \"@/lib/propsContext\";\nimport { OptionsButton } from \"@/components/List/components/Items/components/Item/components/OptionsButton\";\nimport { useListSelector } from \"@/components/List/hooks/useListSelector\";\nimport type { ColumnLayoutProps } from \"@/components/ColumnLayout\";\nimport { flowComponent } from \"@/lib/componentFactory/flowComponent\";\nimport { UiComponentTunnelExit } from \"@/components/UiComponentTunnel/UiComponentTunnelExit\";\n\n/*\n * Built once per view mode: a new object on every render would hand every item\n * a new props context and re-render its content.\n */\nconst buttonTunnel = {\n id: \"button\",\n component: \"ListItemView\",\n} as const;\n\nconst buildPropsContext = (buttonSize: \"s\" | \"m\"): PropsContext => ({\n ...overlayTriggersTunneledTo(buttonTunnel),\n ContextMenu: {\n tunnel: buttonTunnel,\n placement: \"bottom right\",\n wrapWith: <OptionsButton className={styles.action} />,\n },\n Button: {\n tunnel: buttonTunnel,\n size: buttonSize,\n },\n ActionGroup: {\n tunnel: buttonTunnel,\n Button: {\n tunnel: null,\n },\n },\n Avatar: {\n tunnel: {\n id: \"avatar\",\n component: \"ListItemView\",\n },\n },\n Heading: {\n tunnel: {\n id: \"title\",\n component: \"ListItemView\",\n },\n },\n Text: {\n tunnel: {\n id: \"text\",\n component: \"ListItemView\",\n },\n },\n Content: {\n tunnel: dynamic((p) =>\n p.slot === \"bottom\"\n ? {\n id: \"bottom\",\n component: \"ListItemView\",\n }\n : undefined,\n ),\n },\n Checkbox: {\n tunnel: {\n id: \"checkbox\",\n component: \"ListItemView\",\n },\n },\n});\n\nconst listPropsContext = buildPropsContext(\"m\");\nconst tilesPropsContext = buildPropsContext(\"s\");\n\nexport type ListItemViewProps = PropsWithChildren &\n Pick<ColumnLayoutProps, \"s\" | \"m\" | \"l\">;\n\nexport const ListItemView = flowComponent(\n \"ListItemView\",\n (props: ListItemViewProps) => {\n const { children, s, m, l } = props;\n const viewMode = useListSelector((list) => list.viewMode.value);\n const propsContext =\n viewMode === \"tiles\" ? tilesPropsContext : listPropsContext;\n\n return (\n <ListItemViewContentView\n viewMode={viewMode}\n title={<UiComponentTunnelExit id=\"title\" component=\"ListItemView\" />}\n avatar={<UiComponentTunnelExit id=\"avatar\" component=\"ListItemView\" />}\n button={<UiComponentTunnelExit id=\"button\" component=\"ListItemView\" />}\n subTitle={<UiComponentTunnelExit id=\"text\" component=\"ListItemView\" />}\n bottom={<UiComponentTunnelExit id=\"bottom\" component=\"ListItemView\" />}\n checkbox={\n <UiComponentTunnelExit id=\"checkbox\" component=\"ListItemView\" />\n }\n s={s}\n m={m}\n l={l}\n >\n <PropsContextProvider props={propsContext}>\n {children}\n </PropsContextProvider>\n </ListItemViewContentView>\n );\n },\n {\n type: \"layout\",\n },\n);\n\nexport default ListItemView;\n"],"mappings":";;;;;;;;;;;;;AAmBA,IAAM,eAAe;CACnB,IAAI;CACJ,WAAW;AACb;AAEA,IAAM,qBAAqB,gBAAyC;CAClE,GAAG,0BAA0B,YAAY;CACzC,aAAa;EACX,QAAQ;EACR,WAAW;EACX,UAAU,oBAAC,eAAD,EAAe,WAAWA,4BAAO,OAAS,CAAA;CACtD;CACA,QAAQ;EACN,QAAQ;EACR,MAAM;CACR;CACA,aAAa;EACX,QAAQ;EACR,QAAQ,EACN,QAAQ,KACV;CACF;CACA,QAAQ,EACN,QAAQ;EACN,IAAI;EACJ,WAAW;CACb,EACF;CACA,SAAS,EACP,QAAQ;EACN,IAAI;EACJ,WAAW;CACb,EACF;CACA,MAAM,EACJ,QAAQ;EACN,IAAI;EACJ,WAAW;CACb,EACF;CACA,SAAS,EACP,QAAQ,SAAS,MACf,EAAE,SAAS,WACP;EACE,IAAI;EACJ,WAAW;CACb,IACA,KAAA,CACN,EACF;CACA,UAAU,EACR,QAAQ;EACN,IAAI;EACJ,WAAW;CACb,EACF;AACF;AAEA,IAAM,mBAAmB,kBAAkB,GAAG;AAC9C,IAAM,oBAAoB,kBAAkB,GAAG;AAK/C,IAAa,eAAe,cAC1B,iBACC,UAA6B;CAC5B,MAAM,EAAE,UAAU,GAAG,GAAG,MAAM;CAC9B,MAAM,WAAW,iBAAiB,SAAS,KAAK,SAAS,KAAK;CAI9D,OACE,oBAAC,yBAAD;EACY;EACV,OAAO,oBAAC,uBAAD;GAAuB,IAAG;GAAQ,WAAU;EAAgB,CAAA;EACnE,QAAQ,oBAAC,uBAAD;GAAuB,IAAG;GAAS,WAAU;EAAgB,CAAA;EACrE,QAAQ,oBAAC,uBAAD;GAAuB,IAAG;GAAS,WAAU;EAAgB,CAAA;EACrE,UAAU,oBAAC,uBAAD;GAAuB,IAAG;GAAO,WAAU;EAAgB,CAAA;EACrE,QAAQ,oBAAC,uBAAD;GAAuB,IAAG;GAAS,WAAU;EAAgB,CAAA;EACrE,UACE,oBAAC,uBAAD;GAAuB,IAAG;GAAW,WAAU;EAAgB,CAAA;EAE9D;EACA;EACA;EAEH,UAAA,oBAAC,sBAAD;GAAsB,OAjBxB,aAAa,UAAU,oBAAoB;GAkBtC;EACmB,CAAA;CACC,CAAA;AAE7B,GACA,EACE,MAAM,SACR,CACF"}
|
|
@@ -9,34 +9,34 @@ import clsx from "clsx";
|
|
|
9
9
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
//#region src/components/List/components/ListItemView/components/ListItemViewContent/ListItemViewContent.tsx
|
|
11
11
|
var getStyleForContentSlot = (slot) => slot === "bottom" ? clsx(ListItemView_module_default.bottomContent, Item_module_default.bottomContent) : ListItemView_module_default.topContent;
|
|
12
|
+
var contentProps = { bottom: {
|
|
13
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
14
|
+
onPointerDown: (e) => e.stopPropagation()
|
|
15
|
+
} };
|
|
16
|
+
var propsContext = {
|
|
17
|
+
ContextMenu: { placement: "bottom end" },
|
|
18
|
+
Button: { className: ListItemView_module_default.action },
|
|
19
|
+
ActionGroup: { className: ListItemView_module_default.action },
|
|
20
|
+
Content: {
|
|
21
|
+
className: dynamic((p) => getStyleForContentSlot(p.slot)),
|
|
22
|
+
onMouseDown: dynamic((p) => contentProps[p.slot ?? "top"]?.onMouseDown),
|
|
23
|
+
onPointerDown: dynamic((p) => contentProps[p.slot ?? "top"]?.onPointerDown)
|
|
24
|
+
},
|
|
25
|
+
Avatar: { className: ListItemView_module_default.avatar },
|
|
26
|
+
Heading: {
|
|
27
|
+
className: ListItemView_module_default.heading,
|
|
28
|
+
level: 5,
|
|
29
|
+
size: "xs",
|
|
30
|
+
elementType: "span",
|
|
31
|
+
Badge: { className: ListItemView_module_default.badge },
|
|
32
|
+
AlertBadge: { className: ListItemView_module_default.badge }
|
|
33
|
+
},
|
|
34
|
+
Text: { className: ListItemView_module_default.text },
|
|
35
|
+
Link: { unstyled: true }
|
|
36
|
+
};
|
|
12
37
|
/** @flr-generate all */
|
|
13
38
|
var ListItemViewContent = (props) => {
|
|
14
39
|
const { children, avatar, title, subTitle, button, bottom, checkbox, viewMode, s, m, l } = props;
|
|
15
|
-
const contentProps = { bottom: {
|
|
16
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
17
|
-
onPointerDown: (e) => e.stopPropagation()
|
|
18
|
-
} };
|
|
19
|
-
const propsContext = {
|
|
20
|
-
ContextMenu: { placement: "bottom end" },
|
|
21
|
-
Button: { className: ListItemView_module_default.action },
|
|
22
|
-
ActionGroup: { className: ListItemView_module_default.action },
|
|
23
|
-
Content: {
|
|
24
|
-
className: dynamic((p) => getStyleForContentSlot(p.slot)),
|
|
25
|
-
onMouseDown: dynamic((p) => contentProps[p.slot ?? "top"]?.onMouseDown),
|
|
26
|
-
onPointerDown: dynamic((p) => contentProps[p.slot ?? "top"]?.onPointerDown)
|
|
27
|
-
},
|
|
28
|
-
Avatar: { className: ListItemView_module_default.avatar },
|
|
29
|
-
Heading: {
|
|
30
|
-
className: ListItemView_module_default.heading,
|
|
31
|
-
level: 5,
|
|
32
|
-
size: "xs",
|
|
33
|
-
elementType: "span",
|
|
34
|
-
Badge: { className: ListItemView_module_default.badge },
|
|
35
|
-
AlertBadge: { className: ListItemView_module_default.badge }
|
|
36
|
-
},
|
|
37
|
-
Text: { className: ListItemView_module_default.text },
|
|
38
|
-
Link: { unstyled: true }
|
|
39
|
-
};
|
|
40
40
|
const className = clsx(ListItemView_module_default.view, viewMode === "tiles" ? ListItemView_module_default.tileView : ListItemView_module_default.listView);
|
|
41
41
|
const header = /* @__PURE__ */ jsxs("div", {
|
|
42
42
|
className: ListItemView_module_default.header,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListItemViewContent.mjs","names":["styles","itemStyles","_Fragment"],"sources":["../../../../../../../../../../../src/components/List/components/ListItemView/components/ListItemViewContent/ListItemViewContent.tsx"],"sourcesContent":["import type { ComponentProps, PropsWithChildren, ReactNode } from \"react\";\nimport styles from \"../../ListItemView.module.scss\";\nimport itemStyles from \"@/components/List/components/Items/components/Item/Item.module.scss\";\nimport {\n dynamic,\n type PropsContext,\n PropsContextProvider,\n} from \"@/lib/propsContext\";\nimport type { ListViewMode } from \"@/components/List/model/types\";\nimport clsx from \"clsx\";\nimport {\n ColumnLayout,\n type ColumnLayoutProps,\n} from \"@/components/ColumnLayout\";\n\nexport type ListItemViewContentProps = PropsWithChildren &\n Pick<ColumnLayoutProps, \"s\" | \"m\" | \"l\"> & {\n title?: ReactNode;\n subTitle?: ReactNode;\n avatar?: ReactNode;\n button?: ReactNode;\n bottom?: ReactNode;\n checkbox?: ReactNode;\n viewMode?: ListViewMode;\n };\n\n/*\n * The bottom content also carries Item's own `bottomContent` class.\n * Item.module.scss uses it to exclude this area from the item's hover and\n * pressed background — it has its own interactive elements.\n */\nconst getStyleForContentSlot = (slot?: string) =>\n slot === \"bottom\"\n ? clsx(styles.bottomContent, itemStyles.bottomContent)\n : styles.topContent;\n\
|
|
1
|
+
{"version":3,"file":"ListItemViewContent.mjs","names":["styles","itemStyles","_Fragment"],"sources":["../../../../../../../../../../../src/components/List/components/ListItemView/components/ListItemViewContent/ListItemViewContent.tsx"],"sourcesContent":["import type { ComponentProps, PropsWithChildren, ReactNode } from \"react\";\nimport styles from \"../../ListItemView.module.scss\";\nimport itemStyles from \"@/components/List/components/Items/components/Item/Item.module.scss\";\nimport {\n dynamic,\n type PropsContext,\n PropsContextProvider,\n} from \"@/lib/propsContext\";\nimport type { ListViewMode } from \"@/components/List/model/types\";\nimport clsx from \"clsx\";\nimport {\n ColumnLayout,\n type ColumnLayoutProps,\n} from \"@/components/ColumnLayout\";\n\nexport type ListItemViewContentProps = PropsWithChildren &\n Pick<ColumnLayoutProps, \"s\" | \"m\" | \"l\"> & {\n title?: ReactNode;\n subTitle?: ReactNode;\n avatar?: ReactNode;\n button?: ReactNode;\n bottom?: ReactNode;\n checkbox?: ReactNode;\n viewMode?: ListViewMode;\n };\n\n/*\n * The bottom content also carries Item's own `bottomContent` class.\n * Item.module.scss uses it to exclude this area from the item's hover and\n * pressed background — it has its own interactive elements.\n */\nconst getStyleForContentSlot = (slot?: string) =>\n slot === \"bottom\"\n ? clsx(styles.bottomContent, itemStyles.bottomContent)\n : styles.topContent;\n\nconst contentProps: Record<string, ComponentProps<\"div\">> = {\n bottom: {\n onMouseDown: (e) => e.stopPropagation(),\n onPointerDown: (e) => e.stopPropagation(),\n },\n};\n\nconst propsContext: PropsContext = {\n ContextMenu: {\n placement: \"bottom end\",\n },\n Button: {\n className: styles.action,\n },\n ActionGroup: {\n className: styles.action,\n },\n Content: {\n className: dynamic((p) => getStyleForContentSlot(p.slot)),\n onMouseDown: dynamic((p) => contentProps[p.slot ?? \"top\"]?.onMouseDown),\n onPointerDown: dynamic((p) => contentProps[p.slot ?? \"top\"]?.onPointerDown),\n },\n Avatar: {\n className: styles.avatar,\n },\n Heading: {\n className: styles.heading,\n level: 5,\n size: \"xs\",\n elementType: \"span\",\n Badge: { className: styles.badge },\n AlertBadge: { className: styles.badge },\n },\n Text: {\n className: styles.text,\n },\n Link: {\n unstyled: true,\n },\n};\n\n/** @flr-generate all */\nexport const ListItemViewContent = (props: ListItemViewContentProps) => {\n const {\n children,\n avatar,\n title,\n subTitle,\n button,\n bottom,\n checkbox,\n viewMode,\n s,\n m,\n l,\n } = props;\n\n const className = clsx(\n styles.view,\n viewMode === \"tiles\" ? styles.tileView : styles.listView,\n );\n\n const header = (\n <div className={styles.header}>\n <div className={styles.checkboxContainer}>{checkbox}</div>\n {avatar}\n <div className={styles.title}>\n {title}\n <div className={styles.subTitle}>{subTitle}</div>\n </div>\n </div>\n );\n\n const innerListContent = (\n <>\n {header}\n {children}\n </>\n );\n\n const listColumnsContentView = (\n <ColumnLayout\n s={s}\n m={m}\n l={l}\n className={clsx(styles.content, styles.columnLayout)}\n >\n {innerListContent}\n </ColumnLayout>\n );\n\n const listDefaultContentView = (\n <div className={styles.content}>{innerListContent}</div>\n );\n\n const listView = (\n <>\n <div className={styles.contentWrapper}>\n {s || m || l ? listColumnsContentView : listDefaultContentView}\n {button}\n </div>\n {bottom}\n </>\n );\n\n const tilesViews = (\n <>\n <div className={styles.avatarContainer}>{avatar}</div>\n <div className={styles.content}>\n <div className={styles.header}>\n <div className={styles.checkboxContainer}>{checkbox}</div>\n <div className={styles.title}>\n {title}\n <div className={styles.subTitle}>{subTitle}</div>\n </div>\n {button}\n </div>\n {children}\n {bottom}\n </div>\n </>\n );\n\n return (\n <div className={className}>\n <PropsContextProvider props={propsContext}>\n {viewMode === \"list\" && listView}\n {viewMode === \"tiles\" && tilesViews}\n </PropsContextProvider>\n </div>\n );\n};\n\nexport default ListItemViewContent;\n"],"mappings":";;;;;;;;;;AA+BA,IAAM,0BAA0B,SAC9B,SAAS,WACL,KAAKA,4BAAO,eAAeC,oBAAW,aAAa,IACnDD,4BAAO;AAEb,IAAM,eAAsD,EAC1D,QAAQ;CACN,cAAc,MAAM,EAAE,gBAAgB;CACtC,gBAAgB,MAAM,EAAE,gBAAgB;AAC1C,EACF;AAEA,IAAM,eAA6B;CACjC,aAAa,EACX,WAAW,aACb;CACA,QAAQ,EACN,WAAWA,4BAAO,OACpB;CACA,aAAa,EACX,WAAWA,4BAAO,OACpB;CACA,SAAS;EACP,WAAW,SAAS,MAAM,uBAAuB,EAAE,IAAI,CAAC;EACxD,aAAa,SAAS,MAAM,aAAa,EAAE,QAAQ,MAAM,EAAE,WAAW;EACtE,eAAe,SAAS,MAAM,aAAa,EAAE,QAAQ,MAAM,EAAE,aAAa;CAC5E;CACA,QAAQ,EACN,WAAWA,4BAAO,OACpB;CACA,SAAS;EACP,WAAWA,4BAAO;EAClB,OAAO;EACP,MAAM;EACN,aAAa;EACb,OAAO,EAAE,WAAWA,4BAAO,MAAM;EACjC,YAAY,EAAE,WAAWA,4BAAO,MAAM;CACxC;CACA,MAAM,EACJ,WAAWA,4BAAO,KACpB;CACA,MAAM,EACJ,UAAU,KACZ;AACF;;AAGA,IAAa,uBAAuB,UAAoC;CACtE,MAAM,EACJ,UACA,QACA,OACA,UACA,QACA,QACA,UACA,UACA,GACA,GACA,MACE;CAEJ,MAAM,YAAY,KAChBA,4BAAO,MACP,aAAa,UAAUA,4BAAO,WAAWA,4BAAO,QAClD;CAEA,MAAM,SACJ,qBAAC,OAAD;EAAK,WAAWA,4BAAO;EAAvB,UAAA;GACE,oBAAC,OAAD;IAAK,WAAWA,4BAAO;IAAoB,UAAA;GAAc,CAAA;GACxD;GACD,qBAAC,OAAD;IAAK,WAAWA,4BAAO;IAAvB,UAAA,CACG,OACD,oBAAC,OAAD;KAAK,WAAWA,4BAAO;KAAW,UAAA;IAAc,CAAA,CAC7C;;EACF;;CAGP,MAAM,mBACJ,qBAAAE,UAAA,EAAA,UAAA,CACG,QACA,QACD,EAAA,CAAA;CAGJ,MAAM,yBACJ,oBAAC,cAAD;EACK;EACA;EACA;EACH,WAAW,KAAKF,4BAAO,SAASA,4BAAO,YAAY;EAElD,UAAA;CACW,CAAA;CAGhB,MAAM,yBACJ,oBAAC,OAAD;EAAK,WAAWA,4BAAO;EAAU,UAAA;CAAsB,CAAA;CAGzD,MAAM,WACJ,qBAAAE,UAAA,EAAA,UAAA,CACE,qBAAC,OAAD;EAAK,WAAWF,4BAAO;EAAvB,UAAA,CACG,KAAK,KAAK,IAAI,yBAAyB,wBACvC,MACE;CACJ,CAAA,GAAA,MACD,EAAA,CAAA;CAGJ,MAAM,aACJ,qBAAAE,UAAA,EAAA,UAAA,CACE,oBAAC,OAAD;EAAK,WAAWF,4BAAO;EAAkB,UAAA;CAAY,CAAA,GACrD,qBAAC,OAAD;EAAK,WAAWA,4BAAO;EAAvB,UAAA;GACE,qBAAC,OAAD;IAAK,WAAWA,4BAAO;IAAvB,UAAA;KACE,oBAAC,OAAD;MAAK,WAAWA,4BAAO;MAAoB,UAAA;KAAc,CAAA;KACzD,qBAAC,OAAD;MAAK,WAAWA,4BAAO;MAAvB,UAAA,CACG,OACD,oBAAC,OAAD;OAAK,WAAWA,4BAAO;OAAW,UAAA;MAAc,CAAA,CAC7C;;KACJ;IACE;;GACJ;GACA;EACE;CACL,CAAA,CAAA,EAAA,CAAA;CAGJ,OACE,oBAAC,OAAD;EAAgB;EACd,UAAA,qBAAC,sBAAD;GAAsB,OAAO;GAA7B,UAAA,CACG,aAAa,UAAU,UACvB,aAAa,WAAW,UACL;;CACnB,CAAA;AAET"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
/* */
|
|
3
|
+
import { listStoreContext } from "../listContext.mjs";
|
|
4
|
+
import { useContext, useSyncExternalStore } from "react";
|
|
5
|
+
//#region src/components/List/hooks/useListSelector.ts
|
|
6
|
+
/**
|
|
7
|
+
* A value read from the list model, re-rendering only when it changes. The
|
|
8
|
+
* selector has to return a primitive or a value that keeps its identity.
|
|
9
|
+
*/
|
|
10
|
+
var useListSelector = (selector) => {
|
|
11
|
+
const store = useContext(listStoreContext);
|
|
12
|
+
const getValue = () => selector(store.getList());
|
|
13
|
+
return useSyncExternalStore(store.subscribe, getValue, getValue);
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { useListSelector };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=useListSelector.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useListSelector.mjs","names":[],"sources":["../../../../../../../../src/components/List/hooks/useListSelector.ts"],"sourcesContent":["import { useContext, useSyncExternalStore } from \"react\";\nimport { listStoreContext } from \"@/components/List/listContext\";\nimport type List from \"@/components/List/model/List\";\n\n/**\n * A value read from the list model, re-rendering only when it changes. The\n * selector has to return a primitive or a value that keeps its identity.\n */\nexport const useListSelector = <R, T = never>(\n selector: (list: List<T>) => R,\n): R => {\n const store = useContext(listStoreContext);\n const getValue = () => selector(store.getList() as unknown as List<T>);\n return useSyncExternalStore(store.subscribe, getValue, getValue);\n};\n"],"mappings":";;;;;;;;;AAQA,IAAa,mBACX,aACM;CACN,MAAM,QAAQ,WAAW,gBAAgB;CACzC,MAAM,iBAAiB,SAAS,MAAM,QAAQ,CAAuB;CACrE,OAAO,qBAAqB,MAAM,WAAW,UAAU,QAAQ;AACjE"}
|
|
@@ -1,9 +1,39 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
/* */
|
|
3
|
-
import { createContext } from "react";
|
|
3
|
+
import { createContext, useLayoutEffect, useState } from "react";
|
|
4
4
|
//#region src/components/List/listContext.ts
|
|
5
5
|
var listContext = createContext({});
|
|
6
|
+
/**
|
|
7
|
+
* Hands the committed list model to `useListSelector` without changing the
|
|
8
|
+
* context value. The model is rebuilt on every render of `List`; read from
|
|
9
|
+
* `listContext`, it re-renders every consumer, including the ones inside items
|
|
10
|
+
* that skip their own render. A selector re-renders only when the value it
|
|
11
|
+
* reads changes.
|
|
12
|
+
*/
|
|
13
|
+
var ListContextStore = class ListContextStore {
|
|
14
|
+
list;
|
|
15
|
+
listeners = /* @__PURE__ */ new Set();
|
|
16
|
+
constructor(list) {
|
|
17
|
+
this.list = list;
|
|
18
|
+
}
|
|
19
|
+
static useNew(list) {
|
|
20
|
+
const store = useState(() => new ListContextStore(list))[0];
|
|
21
|
+
useLayoutEffect(() => {
|
|
22
|
+
store.list = list;
|
|
23
|
+
store.listeners.forEach((listener) => listener());
|
|
24
|
+
});
|
|
25
|
+
return store;
|
|
26
|
+
}
|
|
27
|
+
getList = () => this.list;
|
|
28
|
+
subscribe = (listener) => {
|
|
29
|
+
this.listeners.add(listener);
|
|
30
|
+
return () => {
|
|
31
|
+
this.listeners.delete(listener);
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
var listStoreContext = createContext(new ListContextStore(void 0));
|
|
6
36
|
//#endregion
|
|
7
|
-
export { listContext };
|
|
37
|
+
export { ListContextStore, listContext, listStoreContext };
|
|
8
38
|
|
|
9
39
|
//# sourceMappingURL=listContext.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listContext.mjs","names":[],"sources":["../../../../../../../src/components/List/listContext.ts"],"sourcesContent":["import { createContext } from \"react\";\nimport type List from \"@/components/List/model/List\";\n\ninterface ListContext {\n list: List<never>;\n}\n\nexport const listContext = createContext<ListContext>({} as ListContext);\n"],"mappings":";;;;AAOA,IAAa,cAAc,cAA2B,CAAC,CAAgB"}
|
|
1
|
+
{"version":3,"file":"listContext.mjs","names":[],"sources":["../../../../../../../src/components/List/listContext.ts"],"sourcesContent":["import { createContext, useLayoutEffect, useState } from \"react\";\nimport type List from \"@/components/List/model/List\";\n\ninterface ListContext {\n list: List<never>;\n}\n\nexport const listContext = createContext<ListContext>({} as ListContext);\n\n/**\n * Hands the committed list model to `useListSelector` without changing the\n * context value. The model is rebuilt on every render of `List`; read from\n * `listContext`, it re-renders every consumer, including the ones inside items\n * that skip their own render. A selector re-renders only when the value it\n * reads changes.\n */\nexport class ListContextStore {\n private list: List<never>;\n private readonly listeners = new Set<() => void>();\n\n public constructor(list: List<never>) {\n this.list = list;\n }\n\n public static useNew(list: List<never>): ListContextStore {\n const store = useState(() => new ListContextStore(list))[0];\n useLayoutEffect(() => {\n store.list = list;\n store.listeners.forEach((listener) => listener());\n });\n return store;\n }\n\n public readonly getList = (): List<never> => this.list;\n\n public readonly subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n}\n\nexport const listStoreContext = createContext(\n new ListContextStore(undefined as unknown as List<never>),\n);\n"],"mappings":";;;;AAOA,IAAa,cAAc,cAA2B,CAAC,CAAgB;;;;;;;;AASvE,IAAa,mBAAb,MAAa,iBAAiB;CAC5B;CACA,4BAA6B,IAAI,IAAgB;CAEjD,YAAmB,MAAmB;EACpC,KAAK,OAAO;CACd;CAEA,OAAc,OAAO,MAAqC;EACxD,MAAM,QAAQ,eAAe,IAAI,iBAAiB,IAAI,CAAC,CAAC,CAAC;EACzD,sBAAsB;GACpB,MAAM,OAAO;GACb,MAAM,UAAU,SAAS,aAAa,SAAS,CAAC;EAClD,CAAC;EACD,OAAO;CACT;CAEA,gBAA6C,KAAK;CAElD,aAA6B,aAAuC;EAClE,KAAK,UAAU,IAAI,QAAQ;EAC3B,aAAa;GACX,KAAK,UAAU,OAAO,QAAQ;EAChC;CACF;AACF;AAEA,IAAa,mBAAmB,cAC9B,IAAI,iBAAiB,KAAA,CAAmC,CAC1D"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { default as List } from '../model/List';
|
|
2
|
+
/**
|
|
3
|
+
* A value read from the list model, re-rendering only when it changes. The
|
|
4
|
+
* selector has to return a primitive or a value that keeps its identity.
|
|
5
|
+
*/
|
|
6
|
+
export declare const useListSelector: <R, T = never>(selector: (list: List<T>) => R) => R;
|
|
@@ -3,4 +3,20 @@ interface ListContext {
|
|
|
3
3
|
list: List<never>;
|
|
4
4
|
}
|
|
5
5
|
export declare const listContext: import('react').Context<ListContext>;
|
|
6
|
+
/**
|
|
7
|
+
* Hands the committed list model to `useListSelector` without changing the
|
|
8
|
+
* context value. The model is rebuilt on every render of `List`; read from
|
|
9
|
+
* `listContext`, it re-renders every consumer, including the ones inside items
|
|
10
|
+
* that skip their own render. A selector re-renders only when the value it
|
|
11
|
+
* reads changes.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ListContextStore {
|
|
14
|
+
private list;
|
|
15
|
+
private readonly listeners;
|
|
16
|
+
constructor(list: List<never>);
|
|
17
|
+
static useNew(list: List<never>): ListContextStore;
|
|
18
|
+
readonly getList: () => List<never>;
|
|
19
|
+
readonly subscribe: (listener: () => void) => (() => void);
|
|
20
|
+
}
|
|
21
|
+
export declare const listStoreContext: import('react').Context<ListContextStore>;
|
|
6
22
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mittwald/flow-react-components",
|
|
3
|
-
"version": "1.6.0-next.
|
|
3
|
+
"version": "1.6.0-next.46",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A React implementation of Flow, mittwald’s design system",
|
|
6
6
|
"homepage": "https://flow.mittwald.de",
|
|
@@ -84,9 +84,9 @@
|
|
|
84
84
|
"@internationalized/string-compiler": "^3.4.1",
|
|
85
85
|
"@lezer/common": "^1.5.2",
|
|
86
86
|
"@lezer/highlight": "^1.2.3",
|
|
87
|
-
"@mittwald/flow-icons": "^1.6.0-next.
|
|
87
|
+
"@mittwald/flow-icons": "^1.6.0-next.46",
|
|
88
88
|
"@mittwald/password-tools-js": "^3.0.0",
|
|
89
|
-
"@mittwald/react-tunnel": "^1.6.0-next.
|
|
89
|
+
"@mittwald/react-tunnel": "^1.6.0-next.46",
|
|
90
90
|
"@mittwald/react-use-promise": "^4.2.2",
|
|
91
91
|
"@react-aria/form": "^3.2.1",
|
|
92
92
|
"@react-aria/i18n": "^3.13.1",
|
|
@@ -139,13 +139,13 @@
|
|
|
139
139
|
"@internationalized/date": "^3.12.3",
|
|
140
140
|
"@lezer/generator": "^1.8.0",
|
|
141
141
|
"@lezer/lr": "^1.4.10",
|
|
142
|
-
"@mittwald/flow-components-base": "1.6.0-next.
|
|
143
|
-
"@mittwald/flow-core": "1.6.0-next.
|
|
144
|
-
"@mittwald/flow-design-tokens": "1.6.0-next.
|
|
145
|
-
"@mittwald/flow-icons-base": "1.6.0-next.
|
|
142
|
+
"@mittwald/flow-components-base": "1.6.0-next.46",
|
|
143
|
+
"@mittwald/flow-core": "1.6.0-next.46",
|
|
144
|
+
"@mittwald/flow-design-tokens": "1.6.0-next.46",
|
|
145
|
+
"@mittwald/flow-icons-base": "1.6.0-next.46",
|
|
146
146
|
"@mittwald/react-use-promise": "^4.2.2",
|
|
147
147
|
"@mittwald/remote-dom-react": "1.2.2-mittwald.10",
|
|
148
|
-
"@mittwald/typescript-config": "1.6.0-next.
|
|
148
|
+
"@mittwald/typescript-config": "1.6.0-next.46",
|
|
149
149
|
"@nx/storybook": "^22.7.6",
|
|
150
150
|
"@storybook/addon-a11y": "^10.5.10",
|
|
151
151
|
"@storybook/addon-actions": "^9.0.8",
|
|
@@ -199,7 +199,7 @@
|
|
|
199
199
|
},
|
|
200
200
|
"peerDependencies": {
|
|
201
201
|
"@internationalized/date": "^3.12.2",
|
|
202
|
-
"@mittwald/flow-icons-pro": "1.6.0-next.
|
|
202
|
+
"@mittwald/flow-icons-pro": "1.6.0-next.46",
|
|
203
203
|
"@mittwald/react-use-promise": "^4.2.2",
|
|
204
204
|
"next": "^16.2.3",
|
|
205
205
|
"react": "^19.2.0",
|
|
@@ -223,5 +223,5 @@
|
|
|
223
223
|
"browserslist": [
|
|
224
224
|
"baseline widely available"
|
|
225
225
|
],
|
|
226
|
-
"gitHead": "
|
|
226
|
+
"gitHead": "6d8f9d2068ff8dbc2227243251ca056641cf098f"
|
|
227
227
|
}
|