@vaadin/hilla-react-crud 24.4.0-alpha2 → 24.4.0-alpha3

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/autocrud.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"autocrud.d.ts","sourceRoot":"","sources":["src/autocrud.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAG7F,OAAO,EAAE,KAAK,GAAG,EAAoB,MAAM,OAAO,CAAC;AAGnD,OAAO,EAAE,KAAK,aAAa,EAAuB,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,KAAK,aAAa,EAA8B,MAAM,eAAe,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,KAAK,mBAAmB,EAAsB,MAAM,WAAW,CAAC;AAIzE,MAAM,MAAM,0BAA0B,CAAC,KAAK,IAAI,CAC9C,UAAU,EAAE,KAAK,GAAG,IAAI,EACxB,QAAQ,EAAE,OAAO,KACd,GAAG,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;AAEpC,MAAM,MAAM,iBAAiB,CAAC,MAAM,SAAS,aAAa,IAAI,IAAI,CAChE,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAC9B,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,SAAS,CAClF,GACC,QAAQ,CAAC;IACP;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAC5D,CAAC,CAAC;AAEL,MAAM,MAAM,iBAAiB,CAAC,KAAK,IAAI,IAAI,CACzC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAC7B,OAAO,GAAG,qBAAqB,GAAG,eAAe,GAAG,SAAS,CAC9D,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,MAAM,SAAS,aAAa,GAAG,aAAa,IAAI,mBAAmB,GAC3F,QAAQ,CAAC;IACP;;;;;OAKG;IACH,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACpC;;;;;;;;;;;;;;;OAeG;IACH,KAAK,EAAE,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,SAAS,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACtC;;OAEG;IACH,SAAS,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAC9C,CAAC,CAAC;AAOL;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,MAAM,SAAS,aAAa,EAAE,EACrD,OAAO,EACP,KAAK,EACL,cAAc,EACd,SAAS,EACT,SAAS,EACT,KAAK,EACL,EAAE,EACF,SAAS,GACV,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAoFrC"}
1
+ {"version":3,"file":"autocrud.d.ts","sourceRoot":"","sources":["src/autocrud.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAG7F,OAAO,EAAE,KAAK,GAAG,EAA2B,MAAM,OAAO,CAAC;AAG1D,OAAO,EAAE,KAAK,aAAa,EAAuB,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,KAAK,aAAa,EAA8B,MAAM,eAAe,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,KAAK,mBAAmB,EAAsB,MAAM,WAAW,CAAC;AAIzE,MAAM,MAAM,0BAA0B,CAAC,KAAK,IAAI,CAC9C,UAAU,EAAE,KAAK,GAAG,IAAI,EACxB,QAAQ,EAAE,OAAO,KACd,GAAG,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;AAEpC,MAAM,MAAM,iBAAiB,CAAC,MAAM,SAAS,aAAa,IAAI,IAAI,CAChE,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,EAC9B,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,iBAAiB,GAAG,iBAAiB,GAAG,SAAS,CAClF,GACC,QAAQ,CAAC;IACP;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAC5D,CAAC,CAAC;AAEL,MAAM,MAAM,iBAAiB,CAAC,KAAK,IAAI,IAAI,CACzC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAC7B,OAAO,GAAG,qBAAqB,GAAG,eAAe,GAAG,SAAS,CAC9D,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,MAAM,SAAS,aAAa,GAAG,aAAa,IAAI,mBAAmB,GAC3F,QAAQ,CAAC;IACP;;;;;OAKG;IACH,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACpC;;;;;;;;;;;;;;;OAeG;IACH,KAAK,EAAE,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,SAAS,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACtC;;OAEG;IACH,SAAS,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAC9C,CAAC,CAAC;AAOL;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,MAAM,SAAS,aAAa,EAAE,EACrD,OAAO,EACP,KAAK,EACL,cAAc,EACd,SAAS,EACT,SAAS,EACT,KAAK,EACL,EAAE,EACF,SAAS,GACV,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAwFrC"}
package/autocrud.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Button } from "@vaadin/react-components/Button.js";
3
3
  import { SplitLayout } from "@vaadin/react-components/SplitLayout.js";
4
- import { useRef, useState } from "react";
4
+ import { useId, useRef, useState } from "react";
5
5
  import { AutoCrudDialog } from "./autocrud-dialog.js";
6
6
  import css from "./autocrud.obj.js";
7
7
  import { emptyItem, AutoForm } from "./autoform.js";
@@ -28,6 +28,7 @@ function AutoCrud({
28
28
  const autoGridRef = useRef(null);
29
29
  const { headerRenderer: customFormHeaderRenderer, ...autoFormProps } = formProps ?? {};
30
30
  const formHeaderRenderer = customFormHeaderRenderer ?? defaultFormHeaderRenderer;
31
+ const autoCrudId = useId();
31
32
  function refreshGrid() {
32
33
  autoGridRef.current?.refresh();
33
34
  }
@@ -48,7 +49,8 @@ function AutoCrud({
48
49
  const activeItem = e.detail.value;
49
50
  setItem(activeItem ?? void 0);
50
51
  },
51
- ref: autoGridRef
52
+ ref: autoGridRef,
53
+ "aria-controls": autoFormProps.id ?? `auto-form-${id ?? autoCrudId}`
52
54
  }
53
55
  ),
54
56
  /* @__PURE__ */ jsx("div", { className: "auto-crud-toolbar", children: /* @__PURE__ */ jsx(Button, { theme: "primary", onClick: () => setItem(emptyItem), children: "+ New" }) })
@@ -56,6 +58,7 @@ function AutoCrud({
56
58
  const autoForm = /* @__PURE__ */ jsx(
57
59
  AutoForm,
58
60
  {
61
+ id: autoFormProps.id ?? `auto-form-${id ?? autoCrudId}`,
59
62
  deleteButtonVisible: true,
60
63
  ...autoFormProps,
61
64
  disabled: !item,
package/autocrud.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["src/autocrud.tsx"],
4
- "sourcesContent": ["import type { AbstractModel, DetachedModelConstructor, Value } from '@vaadin/hilla-lit-form';\nimport { Button } from '@vaadin/react-components/Button.js';\nimport { SplitLayout } from '@vaadin/react-components/SplitLayout.js';\nimport { type JSX, useRef, useState } from 'react';\nimport { AutoCrudDialog } from './autocrud-dialog.js';\nimport css from './autocrud.obj.js';\nimport { type AutoFormProps, emptyItem, AutoForm } from './autoform.js';\nimport { type AutoGridProps, AutoGrid, type AutoGridRef } from './autogrid.js';\nimport type { CrudService } from './crud.js';\nimport { useMediaQuery } from './media-query.js';\nimport { type ComponentStyleProps, registerStylesheet } from './util.js';\n\nregisterStylesheet(css);\n\nexport type AutoCrudFormHeaderRenderer<TItem> = (\n editedItem: TItem | null,\n disabled: boolean,\n) => JSX.Element | null | undefined;\n\nexport type AutoCrudFormProps<TModel extends AbstractModel> = Omit<\n Partial<AutoFormProps<TModel>>,\n 'disabled' | 'item' | 'model' | 'onDeleteSuccess' | 'onSubmitSuccess' | 'service'\n> &\n Readonly<{\n /**\n * A custom renderer function to create the header for the form. The\n * function receives the edited item as the first parameter, and a boolean\n * indicating whether the form is disabled as the second parameter. The\n * edited item is `null` when creating a new item.\n *\n * By default, the header shows \"New item\" when creating a new item, and\n * \"Edit item\" when editing an existing item.\n */\n headerRenderer?: AutoCrudFormHeaderRenderer<Value<TModel>>;\n }>;\n\nexport type AutoCrudGridProps<TItem> = Omit<\n Partial<AutoGridProps<TItem>>,\n 'model' | 'onActiveItemChanged' | 'selectedItems' | 'service'\n>;\n\nexport type AutoCrudProps<TModel extends AbstractModel = AbstractModel> = ComponentStyleProps &\n Readonly<{\n /**\n * The service to use for fetching the data, as well saving and deleting\n * items. This must be a TypeScript service that has been generated by Hilla\n * from a backend Java service that implements the\n * `com.vaadin.hilla.crud.CrudService` interface.\n */\n service: CrudService<Value<TModel>>;\n /**\n * The entity model to use for the CRUD. This determines which columns to\n * show in the grid, and which fields to show in the form. This must be a\n * Typescript model class that has been generated by Hilla from a backend\n * Java class. The model must match with the type of the items returned by\n * the service. For example, a `PersonModel` can be used with a service that\n * returns `Person` instances.\n *\n * By default, the grid shows columns for all properties of the model which\n * have a type that is supported. Use the `gridProps.visibleColumns` option\n * to customize which columns to show and in which order.\n *\n * By default, the form shows fields for all properties of the model which\n * have a type that is supported. Use the `formProps.visibleFields`\n * option to customize which fields to show and in which order.\n */\n model: DetachedModelConstructor<TModel>;\n /**\n * The property to use to detect an item's ID. The item ID is required for\n * deleting items via the `CrudService.delete` method as well as keeping the\n * selection state after reloading the grid.\n *\n * By default, the component uses the property annotated with\n * `jakarta.persistence.Id`, or a property named `id`, in that order.\n * This option can be used to override the default behavior, or define the ID\n * property in case a class doesn't have a property matching the defaults.\n */\n itemIdProperty?: string;\n /**\n * Props to pass to the form. See the `AutoForm` component for details.\n */\n formProps?: AutoCrudFormProps<TModel>;\n /**\n * Props to pass to the grid. See the `AutoGrid` component for details.\n */\n gridProps?: AutoCrudGridProps<Value<TModel>>;\n }>;\n\nfunction defaultFormHeaderRenderer<TItem>(editedItem: TItem | null, disabled: boolean): JSX.Element | null | undefined {\n const style = { color: disabled ? 'var(--lumo-disabled-text-color)' : 'var(--lumo-text-color)' };\n return editedItem ? <h3 style={style}>Edit item</h3> : <h3 style={style}>New item</h3>;\n}\n\n/**\n * Auto CRUD is a component that provides CRUD (create, read, update, delete)\n * functionality based on a Java backend service. It automatically generates a\n * grid that shows data from the service, and a form for creating, updating and\n * deleting items.\n *\n * Example usage:\n * ```tsx\n * import { AutoCrud } from '@hilla/react-crud';\n * import PersonService from 'Frontend/generated/endpoints';\n * import PersonModel from 'Frontend/generated/com/example/application/Person';\n *\n * <AutoCrud service={PersonService} model={PersonModel} />\n * ```\n */\nexport function AutoCrud<TModel extends AbstractModel>({\n service,\n model,\n itemIdProperty,\n formProps,\n gridProps,\n style,\n id,\n className,\n}: AutoCrudProps<TModel>): JSX.Element {\n const [item, setItem] = useState<Value<TModel> | typeof emptyItem | undefined>(undefined);\n const fullScreen = useMediaQuery('(max-width: 600px), (max-height: 600px)');\n const autoGridRef = useRef<AutoGridRef>(null);\n const { headerRenderer: customFormHeaderRenderer, ...autoFormProps } = formProps ?? {};\n const formHeaderRenderer: AutoCrudFormHeaderRenderer<Value<TModel>> =\n customFormHeaderRenderer ?? defaultFormHeaderRenderer;\n\n function refreshGrid() {\n autoGridRef.current?.refresh();\n }\n\n function handleCancel() {\n setItem(undefined);\n }\n\n const formHeader = item && item !== emptyItem ? formHeaderRenderer(item, !item) : formHeaderRenderer(null, !item);\n\n const mainSection = (\n <div className=\"auto-crud-main\">\n <AutoGrid\n {...gridProps}\n service={service}\n model={model as DetachedModelConstructor<AbstractModel<Value<TModel>>>}\n itemIdProperty={itemIdProperty}\n selectedItems={item && item !== emptyItem ? [item] : []}\n onActiveItemChanged={(e) => {\n const activeItem = e.detail.value;\n setItem(activeItem ?? undefined);\n }}\n ref={autoGridRef}\n ></AutoGrid>\n <div className=\"auto-crud-toolbar\">\n <Button theme=\"primary\" onClick={() => setItem(emptyItem)}>\n + New\n </Button>\n </div>\n </div>\n );\n\n const autoForm = (\n <AutoForm\n deleteButtonVisible={true}\n {...autoFormProps}\n disabled={!item}\n service={service}\n model={model}\n itemIdProperty={itemIdProperty}\n item={item}\n onSubmitSuccess={({ item: submittedItem }) => {\n if (fullScreen) {\n setItem(undefined);\n } else {\n setItem(submittedItem);\n }\n refreshGrid();\n }}\n onDeleteSuccess={() => {\n setItem(undefined);\n refreshGrid();\n }}\n />\n );\n\n return (\n <div className={`auto-crud ${className ?? ''}`} id={id} style={style}>\n {fullScreen ? (\n <>\n {mainSection}\n <AutoCrudDialog opened={!!item} header={formHeader} onClose={handleCancel}>\n {autoForm}\n </AutoCrudDialog>\n </>\n ) : (\n <SplitLayout theme=\"small\">\n {mainSection}\n <div className=\"auto-crud-form\">\n <div className=\"auto-crud-form-header\">{formHeader}</div>\n {autoForm}\n </div>\n </SplitLayout>\n )}\n </div>\n );\n}\n"],
5
- "mappings": "AA0FsB,SA8Fd,UA9Fc,KA8ClB,YA9CkB;AAzFtB,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B,SAAmB,QAAQ,gBAAgB;AAC3C,SAAS,sBAAsB;AAC/B,OAAO,SAAS;AAChB,SAA6B,WAAW,gBAAgB;AACxD,SAA6B,gBAAkC;AAE/D,SAAS,qBAAqB;AAC9B,SAAmC,0BAA0B;AAE7D,mBAAmB,GAAG;AA4EtB,SAAS,0BAAiC,YAA0B,UAAmD;AACrH,QAAM,QAAQ,EAAE,OAAO,WAAW,oCAAoC,yBAAyB;AAC/F,SAAO,aAAa,oBAAC,QAAG,OAAc,uBAAS,IAAQ,oBAAC,QAAG,OAAc,sBAAQ;AACnF;AAiBO,SAAS,SAAuC;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuC;AACrC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAuD,MAAS;AACxF,QAAM,aAAa,cAAc,yCAAyC;AAC1E,QAAM,cAAc,OAAoB,IAAI;AAC5C,QAAM,EAAE,gBAAgB,0BAA0B,GAAG,cAAc,IAAI,aAAa,CAAC;AACrF,QAAM,qBACJ,4BAA4B;AAE9B,WAAS,cAAc;AACrB,gBAAY,SAAS,QAAQ;AAAA,EAC/B;AAEA,WAAS,eAAe;AACtB,YAAQ,MAAS;AAAA,EACnB;AAEA,QAAM,aAAa,QAAQ,SAAS,YAAY,mBAAmB,MAAM,CAAC,IAAI,IAAI,mBAAmB,MAAM,CAAC,IAAI;AAEhH,QAAM,cACJ,qBAAC,SAAI,WAAU,kBACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,QAAQ,SAAS,YAAY,CAAC,IAAI,IAAI,CAAC;AAAA,QACtD,qBAAqB,CAAC,MAAM;AAC1B,gBAAM,aAAa,EAAE,OAAO;AAC5B,kBAAQ,cAAc,MAAS;AAAA,QACjC;AAAA,QACA,KAAK;AAAA;AAAA,IACN;AAAA,IACD,oBAAC,SAAI,WAAU,qBACb,8BAAC,UAAO,OAAM,WAAU,SAAS,MAAM,QAAQ,SAAS,GAAG,mBAE3D,GACF;AAAA,KACF;AAGF,QAAM,WACJ;AAAA,IAAC;AAAA;AAAA,MACC,qBAAqB;AAAA,MACpB,GAAG;AAAA,MACJ,UAAU,CAAC;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB,CAAC,EAAE,MAAM,cAAc,MAAM;AAC5C,YAAI,YAAY;AACd,kBAAQ,MAAS;AAAA,QACnB,OAAO;AACL,kBAAQ,aAAa;AAAA,QACvB;AACA,oBAAY;AAAA,MACd;AAAA,MACA,iBAAiB,MAAM;AACrB,gBAAQ,MAAS;AACjB,oBAAY;AAAA,MACd;AAAA;AAAA,EACF;AAGF,SACE,oBAAC,SAAI,WAAW,aAAa,aAAa,EAAE,IAAI,IAAQ,OACrD,uBACC,iCACG;AAAA;AAAA,IACD,oBAAC,kBAAe,QAAQ,CAAC,CAAC,MAAM,QAAQ,YAAY,SAAS,cAC1D,oBACH;AAAA,KACF,IAEA,qBAAC,eAAY,OAAM,SAChB;AAAA;AAAA,IACD,qBAAC,SAAI,WAAU,kBACb;AAAA,0BAAC,SAAI,WAAU,yBAAyB,sBAAW;AAAA,MAClD;AAAA,OACH;AAAA,KACF,GAEJ;AAEJ;",
4
+ "sourcesContent": ["import type { AbstractModel, DetachedModelConstructor, Value } from '@vaadin/hilla-lit-form';\nimport { Button } from '@vaadin/react-components/Button.js';\nimport { SplitLayout } from '@vaadin/react-components/SplitLayout.js';\nimport { type JSX, useId, useRef, useState } from 'react';\nimport { AutoCrudDialog } from './autocrud-dialog.js';\nimport css from './autocrud.obj.js';\nimport { type AutoFormProps, emptyItem, AutoForm } from './autoform.js';\nimport { type AutoGridProps, AutoGrid, type AutoGridRef } from './autogrid.js';\nimport type { CrudService } from './crud.js';\nimport { useMediaQuery } from './media-query.js';\nimport { type ComponentStyleProps, registerStylesheet } from './util.js';\n\nregisterStylesheet(css);\n\nexport type AutoCrudFormHeaderRenderer<TItem> = (\n editedItem: TItem | null,\n disabled: boolean,\n) => JSX.Element | null | undefined;\n\nexport type AutoCrudFormProps<TModel extends AbstractModel> = Omit<\n Partial<AutoFormProps<TModel>>,\n 'disabled' | 'item' | 'model' | 'onDeleteSuccess' | 'onSubmitSuccess' | 'service'\n> &\n Readonly<{\n /**\n * A custom renderer function to create the header for the form. The\n * function receives the edited item as the first parameter, and a boolean\n * indicating whether the form is disabled as the second parameter. The\n * edited item is `null` when creating a new item.\n *\n * By default, the header shows \"New item\" when creating a new item, and\n * \"Edit item\" when editing an existing item.\n */\n headerRenderer?: AutoCrudFormHeaderRenderer<Value<TModel>>;\n }>;\n\nexport type AutoCrudGridProps<TItem> = Omit<\n Partial<AutoGridProps<TItem>>,\n 'model' | 'onActiveItemChanged' | 'selectedItems' | 'service'\n>;\n\nexport type AutoCrudProps<TModel extends AbstractModel = AbstractModel> = ComponentStyleProps &\n Readonly<{\n /**\n * The service to use for fetching the data, as well saving and deleting\n * items. This must be a TypeScript service that has been generated by Hilla\n * from a backend Java service that implements the\n * `com.vaadin.hilla.crud.CrudService` interface.\n */\n service: CrudService<Value<TModel>>;\n /**\n * The entity model to use for the CRUD. This determines which columns to\n * show in the grid, and which fields to show in the form. This must be a\n * Typescript model class that has been generated by Hilla from a backend\n * Java class. The model must match with the type of the items returned by\n * the service. For example, a `PersonModel` can be used with a service that\n * returns `Person` instances.\n *\n * By default, the grid shows columns for all properties of the model which\n * have a type that is supported. Use the `gridProps.visibleColumns` option\n * to customize which columns to show and in which order.\n *\n * By default, the form shows fields for all properties of the model which\n * have a type that is supported. Use the `formProps.visibleFields`\n * option to customize which fields to show and in which order.\n */\n model: DetachedModelConstructor<TModel>;\n /**\n * The property to use to detect an item's ID. The item ID is required for\n * deleting items via the `CrudService.delete` method as well as keeping the\n * selection state after reloading the grid.\n *\n * By default, the component uses the property annotated with\n * `jakarta.persistence.Id`, or a property named `id`, in that order.\n * This option can be used to override the default behavior, or define the ID\n * property in case a class doesn't have a property matching the defaults.\n */\n itemIdProperty?: string;\n /**\n * Props to pass to the form. See the `AutoForm` component for details.\n */\n formProps?: AutoCrudFormProps<TModel>;\n /**\n * Props to pass to the grid. See the `AutoGrid` component for details.\n */\n gridProps?: AutoCrudGridProps<Value<TModel>>;\n }>;\n\nfunction defaultFormHeaderRenderer<TItem>(editedItem: TItem | null, disabled: boolean): JSX.Element | null | undefined {\n const style = { color: disabled ? 'var(--lumo-disabled-text-color)' : 'var(--lumo-text-color)' };\n return editedItem ? <h3 style={style}>Edit item</h3> : <h3 style={style}>New item</h3>;\n}\n\n/**\n * Auto CRUD is a component that provides CRUD (create, read, update, delete)\n * functionality based on a Java backend service. It automatically generates a\n * grid that shows data from the service, and a form for creating, updating and\n * deleting items.\n *\n * Example usage:\n * ```tsx\n * import { AutoCrud } from '@hilla/react-crud';\n * import PersonService from 'Frontend/generated/endpoints';\n * import PersonModel from 'Frontend/generated/com/example/application/Person';\n *\n * <AutoCrud service={PersonService} model={PersonModel} />\n * ```\n */\nexport function AutoCrud<TModel extends AbstractModel>({\n service,\n model,\n itemIdProperty,\n formProps,\n gridProps,\n style,\n id,\n className,\n}: AutoCrudProps<TModel>): JSX.Element {\n const [item, setItem] = useState<Value<TModel> | typeof emptyItem | undefined>(undefined);\n const fullScreen = useMediaQuery('(max-width: 600px), (max-height: 600px)');\n const autoGridRef = useRef<AutoGridRef>(null);\n const { headerRenderer: customFormHeaderRenderer, ...autoFormProps } = formProps ?? {};\n const formHeaderRenderer: AutoCrudFormHeaderRenderer<Value<TModel>> =\n customFormHeaderRenderer ?? defaultFormHeaderRenderer;\n\n const autoCrudId = useId();\n\n function refreshGrid() {\n autoGridRef.current?.refresh();\n }\n\n function handleCancel() {\n setItem(undefined);\n }\n\n const formHeader = item && item !== emptyItem ? formHeaderRenderer(item, !item) : formHeaderRenderer(null, !item);\n\n const mainSection = (\n <div className=\"auto-crud-main\">\n <AutoGrid\n {...gridProps}\n service={service}\n model={model as DetachedModelConstructor<AbstractModel<Value<TModel>>>}\n itemIdProperty={itemIdProperty}\n selectedItems={item && item !== emptyItem ? [item] : []}\n onActiveItemChanged={(e) => {\n const activeItem = e.detail.value;\n setItem(activeItem ?? undefined);\n }}\n ref={autoGridRef}\n aria-controls={autoFormProps.id ?? `auto-form-${id ?? autoCrudId}`}\n ></AutoGrid>\n <div className=\"auto-crud-toolbar\">\n <Button theme=\"primary\" onClick={() => setItem(emptyItem)}>\n + New\n </Button>\n </div>\n </div>\n );\n\n const autoForm = (\n <AutoForm\n id={autoFormProps.id ?? `auto-form-${id ?? autoCrudId}`}\n deleteButtonVisible={true}\n {...autoFormProps}\n disabled={!item}\n service={service}\n model={model}\n itemIdProperty={itemIdProperty}\n item={item}\n onSubmitSuccess={({ item: submittedItem }) => {\n if (fullScreen) {\n setItem(undefined);\n } else {\n setItem(submittedItem);\n }\n refreshGrid();\n }}\n onDeleteSuccess={() => {\n setItem(undefined);\n refreshGrid();\n }}\n />\n );\n\n return (\n <div className={`auto-crud ${className ?? ''}`} id={id} style={style}>\n {fullScreen ? (\n <>\n {mainSection}\n <AutoCrudDialog opened={!!item} header={formHeader} onClose={handleCancel}>\n {autoForm}\n </AutoCrudDialog>\n </>\n ) : (\n <SplitLayout theme=\"small\">\n {mainSection}\n <div className=\"auto-crud-form\">\n <div className=\"auto-crud-form-header\">{formHeader}</div>\n {autoForm}\n </div>\n </SplitLayout>\n )}\n </div>\n );\n}\n"],
5
+ "mappings": "AA0FsB,SAkGd,UAlGc,KAgDlB,YAhDkB;AAzFtB,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B,SAAmB,OAAO,QAAQ,gBAAgB;AAClD,SAAS,sBAAsB;AAC/B,OAAO,SAAS;AAChB,SAA6B,WAAW,gBAAgB;AACxD,SAA6B,gBAAkC;AAE/D,SAAS,qBAAqB;AAC9B,SAAmC,0BAA0B;AAE7D,mBAAmB,GAAG;AA4EtB,SAAS,0BAAiC,YAA0B,UAAmD;AACrH,QAAM,QAAQ,EAAE,OAAO,WAAW,oCAAoC,yBAAyB;AAC/F,SAAO,aAAa,oBAAC,QAAG,OAAc,uBAAS,IAAQ,oBAAC,QAAG,OAAc,sBAAQ;AACnF;AAiBO,SAAS,SAAuC;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuC;AACrC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAuD,MAAS;AACxF,QAAM,aAAa,cAAc,yCAAyC;AAC1E,QAAM,cAAc,OAAoB,IAAI;AAC5C,QAAM,EAAE,gBAAgB,0BAA0B,GAAG,cAAc,IAAI,aAAa,CAAC;AACrF,QAAM,qBACJ,4BAA4B;AAE9B,QAAM,aAAa,MAAM;AAEzB,WAAS,cAAc;AACrB,gBAAY,SAAS,QAAQ;AAAA,EAC/B;AAEA,WAAS,eAAe;AACtB,YAAQ,MAAS;AAAA,EACnB;AAEA,QAAM,aAAa,QAAQ,SAAS,YAAY,mBAAmB,MAAM,CAAC,IAAI,IAAI,mBAAmB,MAAM,CAAC,IAAI;AAEhH,QAAM,cACJ,qBAAC,SAAI,WAAU,kBACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,QAAQ,SAAS,YAAY,CAAC,IAAI,IAAI,CAAC;AAAA,QACtD,qBAAqB,CAAC,MAAM;AAC1B,gBAAM,aAAa,EAAE,OAAO;AAC5B,kBAAQ,cAAc,MAAS;AAAA,QACjC;AAAA,QACA,KAAK;AAAA,QACL,iBAAe,cAAc,MAAM,aAAa,MAAM,UAAU;AAAA;AAAA,IACjE;AAAA,IACD,oBAAC,SAAI,WAAU,qBACb,8BAAC,UAAO,OAAM,WAAU,SAAS,MAAM,QAAQ,SAAS,GAAG,mBAE3D,GACF;AAAA,KACF;AAGF,QAAM,WACJ;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,cAAc,MAAM,aAAa,MAAM,UAAU;AAAA,MACrD,qBAAqB;AAAA,MACpB,GAAG;AAAA,MACJ,UAAU,CAAC;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB,CAAC,EAAE,MAAM,cAAc,MAAM;AAC5C,YAAI,YAAY;AACd,kBAAQ,MAAS;AAAA,QACnB,OAAO;AACL,kBAAQ,aAAa;AAAA,QACvB;AACA,oBAAY;AAAA,MACd;AAAA,MACA,iBAAiB,MAAM;AACrB,gBAAQ,MAAS;AACjB,oBAAY;AAAA,MACd;AAAA;AAAA,EACF;AAGF,SACE,oBAAC,SAAI,WAAW,aAAa,aAAa,EAAE,IAAI,IAAQ,OACrD,uBACC,iCACG;AAAA;AAAA,IACD,oBAAC,kBAAe,QAAQ,CAAC,CAAC,MAAM,QAAQ,YAAY,SAAS,cAC1D,oBACH;AAAA,KACF,IAEA,qBAAC,eAAY,OAAM,SAChB;AAAA;AAAA,IACD,qBAAC,SAAI,WAAU,kBACb;AAAA,0BAAC,SAAI,WAAU,yBAAyB,sBAAW;AAAA,MAClD;AAAA,OACH;AAAA,KACF,GAEJ;AAEJ;",
6
6
  "names": []
7
7
  }
package/autogrid.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"autogrid.d.ts","sourceRoot":"","sources":["src/autogrid.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAQ,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAG1F,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,YAAY,EAEjB,KAAK,GAAG,EAMT,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,uBAAuB,CAAC;AAG7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAyD,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5G,OAAO,EAAE,KAAK,yBAAyB,EAAuC,MAAM,iBAAiB,CAAC;AAItG,OAAO,KAAK,WAAW,MAAM,qDAAqD,CAAC;AAKnF,MAAM,WAAW,WAAW,CAAC,KAAK,GAAG,GAAG;IACtC;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAEhC;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,UAAU,gBAAgB,CAAC,KAAK;IAC9B;;;;OAIG;IACH,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,KAAK,EAAE,wBAAwB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IACtD;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,WAAW,CAAC;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAC9B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC9C;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;CACjD;AAED,MAAM,MAAM,aAAa,CAAC,KAAK,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;AAyJxF,iBAAS,aAAa,CAAC,KAAK,EAC1B,EACE,OAAO,EACP,KAAK,EACL,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU,EACV,aAAa,EACb,mBAAmB,EACnB,GAAG,SAAS,EACb,EAAE,aAAa,CAAC,KAAK,CAAC,EACvB,GAAG,EAAE,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,GACpC,GAAG,CAAC,OAAO,CA0Gb;AAED,KAAK,QAAQ,GAAG,CAAC,KAAK,EACpB,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAA;CAAE,KACrE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AAEtC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAgD,CAAC;AAExE,YAAY,EAAE,aAAa,EAAE,yBAAyB,EAAE,CAAC"}
1
+ {"version":3,"file":"autogrid.d.ts","sourceRoot":"","sources":["src/autogrid.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAQ,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAG1F,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,YAAY,EAEjB,KAAK,GAAG,EAMT,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,KAAK,aAAa,EAAoB,MAAM,uBAAuB,CAAC;AAG7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAyD,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC5G,OAAO,EAAE,KAAK,yBAAyB,EAAuC,MAAM,iBAAiB,CAAC;AAItG,OAAO,KAAK,WAAW,MAAM,qDAAqD,CAAC;AAKnF,MAAM,WAAW,WAAW,CAAC,KAAK,GAAG,GAAG;IACtC;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAEhC;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,UAAU,gBAAgB,CAAC,KAAK;IAC9B;;;;OAIG;IACH,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IAC5B;;;;;;;;;;OAUG;IACH,KAAK,EAAE,wBAAwB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IACtD;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,WAAW,CAAC;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IAC9B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC9C;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;CACjD;AAED,MAAM,MAAM,aAAa,CAAC,KAAK,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;AAyJxF,iBAAS,aAAa,CAAC,KAAK,EAC1B,EACE,OAAO,EACP,KAAK,EACL,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU,EACV,aAAa,EACb,mBAAmB,EACnB,GAAG,SAAS,EACb,EAAE,aAAa,CAAC,KAAK,CAAC,EACvB,GAAG,EAAE,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,GACpC,GAAG,CAAC,OAAO,CAkHb;AAED,KAAK,QAAQ,GAAG,CAAC,KAAK,EACpB,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,YAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAA;CAAE,KACrE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AAEtC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,QAAQ,EAAE,QAAgD,CAAC;AAExE,YAAY,EAAE,aAAa,EAAE,yBAAyB,EAAE,CAAC"}
package/autogrid.js CHANGED
@@ -153,7 +153,8 @@ function AutoGridInner({
153
153
  return gridRef.current;
154
154
  },
155
155
  refresh() {
156
- dataProviderRef.current?.refresh();
156
+ dataProviderRef.current?.reset();
157
+ gridRef.current?.clearCache();
157
158
  }
158
159
  }),
159
160
  []
@@ -198,15 +199,15 @@ function AutoGridInner({
198
199
  }
199
200
  }, [noHeaderFilters]);
200
201
  useEffect(() => {
201
- const grid = gridRef.current;
202
202
  if ((!isCountService(service) && totalCount) ?? filteredCount) {
203
203
  console.error(
204
204
  '"totalCount" and "filteredCount" props require the provided service to implement the CountService interface.'
205
205
  );
206
206
  }
207
- setTimeout(() => {
207
+ const grid = gridRef.current;
208
+ const timeoutId = setTimeout(() => {
208
209
  let firstUpdate = true;
209
- dataProviderRef.current = createDataProvider(grid, service, {
210
+ const dataProvider = createDataProvider(service, {
210
211
  initialFilter: experimentalFilter ?? internalFilter,
211
212
  loadTotalCount: totalCount,
212
213
  afterLoad(newItemCounts) {
@@ -217,12 +218,17 @@ function AutoGridInner({
217
218
  }
218
219
  }
219
220
  });
221
+ dataProviderRef.current = dataProvider;
222
+ gridRef.current.dataProvider = dataProvider.load.bind(dataProvider);
220
223
  }, 1);
224
+ return () => clearTimeout(timeoutId);
221
225
  }, [model, service]);
222
226
  useEffect(() => {
223
227
  const dataProvider = dataProviderRef.current;
224
- if (dataProvider) {
228
+ const grid = gridRef.current;
229
+ if (grid && dataProvider) {
225
230
  dataProvider.setFilter(experimentalFilter ?? internalFilter);
231
+ grid.clearCache();
226
232
  }
227
233
  }, [experimentalFilter, internalFilter]);
228
234
  return /* @__PURE__ */ jsx(Grid, { itemIdPath: modelInfo.idProperty?.name, ...gridProps, ref: gridRef, children });
package/autogrid.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["src/autogrid.tsx"],
4
- "sourcesContent": ["import type { AbstractModel, DetachedModelConstructor } from '@vaadin/hilla-lit-form';\nimport { Grid, type GridElement, type GridProps } from '@vaadin/react-components/Grid.js';\nimport { GridColumn } from '@vaadin/react-components/GridColumn.js';\nimport { GridColumnGroup } from '@vaadin/react-components/GridColumnGroup.js';\nimport {\n cloneElement,\n type ComponentType,\n type ForwardedRef,\n forwardRef,\n type JSX,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { ColumnContext, CustomColumnContext, type SortState } from './autogrid-column-context.js';\nimport { type ColumnOptions, getColumnOptions } from './autogrid-columns.js';\nimport { AutoGridFooterItemCountRenderer, AutoGridRowNumberRenderer, FooterContext } from './autogrid-renderers.js';\nimport css from './autogrid.obj.js';\nimport type { ListService } from './crud';\nimport { createDataProvider, type DataProvider, isCountService, type ItemCounts } from './data-provider.js';\nimport { type HeaderFilterRendererProps, NoHeaderFilter, HeaderFilterWrapper } from './header-filter';\nimport { HeaderSorter } from './header-sorter';\nimport { getDefaultProperties, ModelInfo, type PropertyInfo } from './model-info.js';\nimport type AndFilter from './types/com/vaadin/hilla/crud/filter/AndFilter.js';\nimport type FilterUnion from './types/com/vaadin/hilla/crud/filter/FilterUnion.js';\nimport { isFilterEmpty, registerStylesheet } from './util';\n\nregisterStylesheet(css);\n\nexport interface AutoGridRef<TItem = any> {\n /**\n * The underlying vaadin-grid DOM element.\n */\n grid: GridElement<TItem> | null;\n\n /**\n * Refreshes the grid by reloading the data from the backend.\n */\n refresh(): void;\n}\n\ninterface AutoGridOwnProps<TItem> {\n /**\n * The service to use for fetching the data. This must be a TypeScript service\n * that has been generated by Hilla from a backend Java service that\n * implements the `com.vaadin.hilla.crud.ListService` interface.\n */\n service: ListService<TItem>;\n /**\n * The entity model to use for the grid, which determines which columns to\n * show and how to render them. This must be a Typescript model class that has\n * been generated by Hilla from a backend Java class. The model must match\n * with the type of the items returned by the service. For example, a\n * `PersonModel` can be used with a service that returns `Person` instances.\n *\n * By default, the grid shows columns for all properties of the model which\n * have a type that is supported. Use the `visibleColumns` option to customize\n * which columns to show and in which order.\n */\n model: DetachedModelConstructor<AbstractModel<TItem>>;\n /**\n * The property to use to detect an item's ID. The item ID is used to keep\n * the selection state when reloading the grid.\n *\n * By default, the component uses the property annotated with\n * `jakarta.persistence.Id`, or a property named `id`, in that order.\n * This option can be used to override the default behavior, or define the ID\n * property in case a class doesn't have a property matching the defaults.\n */\n itemIdProperty?: string;\n /**\n * Allows to provide a filter that is applied when fetching data from the\n * service. This can be used for implementing an external filter UI outside\n * the grid. A custom filter is not compatible with header filters.\n *\n * **NOTE:** This is considered an experimental feature and the API may change\n * in the future.\n */\n experimentalFilter?: FilterUnion;\n /**\n * Allows to customize which columns to show and in which order. This must be\n * an array of property names that are defined in the model. Nested properties\n * can be specified using dot notation, e.g. `address.street`.\n */\n visibleColumns?: string[];\n /**\n * Disables header filters, which are otherwise enabled by default.\n */\n noHeaderFilters?: boolean;\n /**\n * Allows to add custom columns to the grid. This must be an array of\n * `GridColumn` component instances. Custom columns are added after the\n * auto-generated columns.\n */\n customColumns?: JSX.Element[];\n /**\n * Allows to customize the props for individual columns. This is an object\n * where the keys must be property names that are defined in the model, and\n * the values are props that are accepted by the `GridColumn` component.\n * Nested properties can be specified using dot notation, e.g.\n * `address.street`.\n */\n columnOptions?: Record<string, ColumnOptions>;\n /**\n * When enabled, inserts a column with row numbers at the beginning of the\n * grid.\n */\n rowNumbers?: boolean;\n /**\n * When enabled, shows the total count of items in the grid footer.\n * This requires the provided service to implement the CountService interface,\n * otherwise an error will be logged to the console, without any count being\n * rendered.\n */\n totalCount?: boolean;\n /**\n * When enabled, shows the filtered item count in the grid footer.\n * if totalCount is also enabled, it will show both totalCount and filteredCount.\n * This requires the provided service to implement the CountService interface,\n * otherwise an error will be logged to the console, without any count being\n * rendered.\n */\n filteredCount?: boolean;\n /**\n * Allows to customize the grid footer with a custom renderer component for\n * the total count and filtered item count.\n * This requires the provided service to implement the CountService interface,\n * See {@link AutoGrid#totalCount} and {@link AutoGrid#filteredCount}.\n */\n footerCountRenderer?: ComponentType<ItemCounts>;\n}\n\nexport type AutoGridProps<TItem> = GridProps<TItem> & Readonly<AutoGridOwnProps<TItem>>;\n\ninterface ColumnConfigurationOptions {\n visibleColumns?: string[];\n noHeaderFilters?: boolean;\n customColumns?: JSX.Element[];\n columnOptions?: Record<string, ColumnOptions>;\n rowNumbers?: boolean;\n totalCount?: boolean;\n filteredCount?: boolean;\n footerCountRenderer?: ComponentType<ItemCounts>;\n itemCounts?: ItemCounts;\n}\n\nfunction wrapCustomColumn(\n column: JSX.Element,\n setColumnFilter: (filter: FilterUnion, filterKey: string) => void,\n options: ColumnConfigurationOptions,\n) {\n const key = column.key ?? 'no-key';\n const { header, headerRenderer } = column.props;\n const customOptions = options.columnOptions?.[key];\n const { header: customHeader, headerRenderer: customHeaderRenderer, headerFilterRenderer } = customOptions ?? {};\n const columnWithoutHeader = cloneElement(column, {\n header: null,\n headerRenderer: HeaderFilterWrapper,\n });\n return (\n <CustomColumnContext.Provider\n key={key}\n value={{\n setColumnFilter,\n headerFilterRenderer: headerFilterRenderer ?? NoHeaderFilter,\n filterKey: key,\n }}\n >\n <GridColumnGroup\n key={key}\n header={customHeader ?? header}\n headerRenderer={customHeaderRenderer ?? headerRenderer}\n >\n {columnWithoutHeader}\n </GridColumnGroup>\n </CustomColumnContext.Provider>\n );\n}\n\nfunction addCustomColumns(\n columns: JSX.Element[],\n options: ColumnConfigurationOptions,\n setColumnFilter: (filter: FilterUnion, filterKey: string) => void,\n): JSX.Element[] {\n if (!options.customColumns) {\n return columns;\n }\n\n // When using header filters, wrap custom columns into column groups and\n // move header text or renderer to group\n const customColumns = options.noHeaderFilters\n ? options.customColumns\n : options.customColumns.map((column) => wrapCustomColumn(column, setColumnFilter, options));\n\n // When using a custom column order, insert custom columns into auto-generated\n // ones using their `key`\n if (options.visibleColumns) {\n const columnMap = [...columns, ...customColumns].reduce((map, column) => {\n const { key } = column;\n if (key) {\n map.set(key, column);\n }\n return map;\n }, new Map<string, JSX.Element>());\n\n return options.visibleColumns.map((path) => columnMap.get(path)).filter(Boolean) as JSX.Element[];\n }\n\n // Otherwise just append custom columns at the end\n return [...columns, ...customColumns];\n}\n\nfunction useColumns(\n properties: PropertyInfo[],\n setColumnFilter: (filter: FilterUnion, filterKey: string) => void,\n options: ColumnConfigurationOptions,\n) {\n const sortableProperties = properties.filter(\n (propertyInfo) => options.columnOptions?.[propertyInfo.name]?.sortable !== false,\n );\n const [sortState, setSortState] = useState<SortState>(\n sortableProperties.length > 0 ? { [sortableProperties[0].name]: { direction: 'asc' } } : {},\n );\n let columns = properties.map((propertyInfo) => {\n let column;\n const customColumnOptions = options.columnOptions?.[propertyInfo.name];\n\n const { headerFilterRenderer, ...columnProps } = getColumnOptions(propertyInfo, customColumnOptions);\n\n if (!options.noHeaderFilters) {\n column = (\n <GridColumnGroup headerRenderer={HeaderSorter}>\n <GridColumn path={propertyInfo.name} headerRenderer={HeaderFilterWrapper} {...columnProps}></GridColumn>\n </GridColumnGroup>\n );\n } else {\n column = <GridColumn path={propertyInfo.name} headerRenderer={HeaderSorter} {...columnProps}></GridColumn>;\n }\n return (\n <ColumnContext.Provider\n key={propertyInfo.name}\n value={{\n propertyInfo,\n setColumnFilter,\n sortState,\n setSortState,\n customColumnOptions,\n headerFilterRenderer: headerFilterRenderer ?? NoHeaderFilter,\n filterKey: propertyInfo.name,\n }}\n >\n {column}\n </ColumnContext.Provider>\n );\n });\n\n columns = addCustomColumns(columns, options, setColumnFilter);\n\n if (options.rowNumbers) {\n columns = [\n <GridColumn key=\"rownumbers\" width=\"4em\" flexGrow={0} renderer={AutoGridRowNumberRenderer}></GridColumn>,\n ...columns,\n ];\n }\n const { totalCount, filteredCount, itemCounts, footerCountRenderer } = options;\n if (totalCount ?? filteredCount) {\n const col = (\n <FooterContext.Provider\n key=\"grid-footer\"\n value={{\n totalCount,\n filteredCount,\n footerCountRenderer,\n itemCounts,\n }}\n >\n <GridColumnGroup footerRenderer={AutoGridFooterItemCountRenderer}>{columns}</GridColumnGroup>\n </FooterContext.Provider>\n );\n columns = [col];\n }\n\n return columns;\n}\n\nfunction AutoGridInner<TItem>(\n {\n service,\n model,\n itemIdProperty,\n experimentalFilter,\n visibleColumns,\n noHeaderFilters,\n customColumns,\n columnOptions,\n rowNumbers,\n totalCount,\n filteredCount,\n footerCountRenderer,\n ...gridProps\n }: AutoGridProps<TItem>,\n ref: ForwardedRef<AutoGridRef<TItem>>,\n): JSX.Element {\n const [internalFilter, setInternalFilter] = useState<AndFilter>({ '@type': 'and', children: [] });\n const [itemCounts, setItemCounts] = useState<ItemCounts | undefined>();\n const gridRef = useRef<GridElement<TItem>>(null);\n const dataProviderRef = useRef<DataProvider<TItem>>();\n\n useImperativeHandle(\n ref,\n () => ({\n get grid() {\n return gridRef.current;\n },\n refresh() {\n dataProviderRef.current?.refresh();\n },\n }),\n [],\n );\n\n const setHeaderFilter = (filter: FilterUnion, filterKey: string) => {\n let changed = false;\n filter.key = filterKey;\n const indexOfFilter = filterKey\n ? internalFilter.children.findIndex((f) => (f as FilterUnion).key === filterKey)\n : -1;\n const isEmptyFilter = isFilterEmpty(filter);\n\n if (indexOfFilter >= 0 && isEmptyFilter) {\n internalFilter.children.splice(indexOfFilter, 1);\n changed = true;\n } else if (!isEmptyFilter) {\n if (indexOfFilter >= 0) {\n internalFilter.children[indexOfFilter] = filter;\n changed = true;\n } else {\n internalFilter.children.push(filter);\n changed = true;\n }\n }\n if (changed) {\n setInternalFilter({ ...internalFilter });\n }\n };\n\n const modelInfo = useMemo(() => new ModelInfo(model, itemIdProperty), [model]);\n const properties = visibleColumns ? modelInfo.getProperties(visibleColumns) : getDefaultProperties(modelInfo);\n const children = useColumns(properties, setHeaderFilter, {\n visibleColumns,\n noHeaderFilters,\n customColumns,\n columnOptions,\n rowNumbers,\n totalCount,\n filteredCount,\n footerCountRenderer,\n itemCounts,\n });\n\n useEffect(() => {\n // Remove all filtering if header filters are removed\n if (noHeaderFilters) {\n setInternalFilter({ '@type': 'and', children: [] });\n }\n }, [noHeaderFilters]);\n\n useEffect(() => {\n // Sets the data provider, should be done only once\n const grid = gridRef.current!;\n // Log an error if totalCount or filteredCount is enabled but the service doesn't implement CountService\n if ((!isCountService(service) && totalCount) ?? filteredCount) {\n console.error(\n '\"totalCount\" and \"filteredCount\" props require the provided service to implement the CountService interface.',\n );\n }\n // Wait for the sorting headers to be rendered so that the sorting state is correct for the first data provider call\n setTimeout(() => {\n let firstUpdate = true;\n dataProviderRef.current = createDataProvider(grid, service, {\n initialFilter: experimentalFilter ?? internalFilter,\n loadTotalCount: totalCount,\n afterLoad(newItemCounts: ItemCounts) {\n setItemCounts(newItemCounts);\n\n if (firstUpdate) {\n // Workaround for https://github.com/vaadin/react-components/issues/129\n firstUpdate = false;\n setTimeout(() => grid.recalculateColumnWidths(), 0);\n }\n },\n });\n }, 1);\n }, [model, service]);\n\n useEffect(() => {\n // Update the filtering, whenever the filter changes\n const dataProvider = dataProviderRef.current;\n if (dataProvider) {\n dataProvider.setFilter(experimentalFilter ?? internalFilter);\n }\n }, [experimentalFilter, internalFilter]);\n\n return (\n <Grid itemIdPath={modelInfo.idProperty?.name} {...gridProps} ref={gridRef}>\n {children}\n </Grid>\n );\n}\n\ntype AutoGrid = <TItem>(\n props: AutoGridProps<TItem> & { ref?: ForwardedRef<AutoGridRef<TItem>> },\n) => ReturnType<typeof AutoGridInner>;\n\n/**\n * Auto Grid is a component for displaying tabular data based on a Java backend\n * service. It automatically generates columns based on the properties of a\n * Java class and provides features such as lazy-loading, sorting and filtering.\n *\n * Example usage:\n * ```tsx\n * import { AutoGrid } from '@hilla/react-crud';\n * import PersonService from 'Frontend/generated/endpoints';\n * import PersonModel from 'Frontend/generated/com/example/application/Person';\n *\n * <AutoGrid service={PersonService} model={PersonModel} />\n * ```\n */\nexport const AutoGrid: AutoGrid = forwardRef(AutoGridInner) as AutoGrid;\n\nexport type { ColumnOptions, HeaderFilterRendererProps };\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { AbstractModel, DetachedModelConstructor } from '@vaadin/hilla-lit-form';\nimport { Grid, type GridElement, type GridProps } from '@vaadin/react-components/Grid.js';\nimport { GridColumn } from '@vaadin/react-components/GridColumn.js';\nimport { GridColumnGroup } from '@vaadin/react-components/GridColumnGroup.js';\nimport {\n cloneElement,\n type ComponentType,\n type ForwardedRef,\n forwardRef,\n type JSX,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { ColumnContext, CustomColumnContext, type SortState } from './autogrid-column-context.js';\nimport { type ColumnOptions, getColumnOptions } from './autogrid-columns.js';\nimport { AutoGridFooterItemCountRenderer, AutoGridRowNumberRenderer, FooterContext } from './autogrid-renderers.js';\nimport css from './autogrid.obj.js';\nimport type { ListService } from './crud';\nimport { createDataProvider, type DataProvider, isCountService, type ItemCounts } from './data-provider.js';\nimport { type HeaderFilterRendererProps, NoHeaderFilter, HeaderFilterWrapper } from './header-filter';\nimport { HeaderSorter } from './header-sorter';\nimport { getDefaultProperties, ModelInfo, type PropertyInfo } from './model-info.js';\nimport type AndFilter from './types/com/vaadin/hilla/crud/filter/AndFilter.js';\nimport type FilterUnion from './types/com/vaadin/hilla/crud/filter/FilterUnion.js';\nimport { isFilterEmpty, registerStylesheet } from './util';\n\nregisterStylesheet(css);\n\nexport interface AutoGridRef<TItem = any> {\n /**\n * The underlying vaadin-grid DOM element.\n */\n grid: GridElement<TItem> | null;\n\n /**\n * Refreshes the grid by reloading the data from the backend.\n */\n refresh(): void;\n}\n\ninterface AutoGridOwnProps<TItem> {\n /**\n * The service to use for fetching the data. This must be a TypeScript service\n * that has been generated by Hilla from a backend Java service that\n * implements the `com.vaadin.hilla.crud.ListService` interface.\n */\n service: ListService<TItem>;\n /**\n * The entity model to use for the grid, which determines which columns to\n * show and how to render them. This must be a Typescript model class that has\n * been generated by Hilla from a backend Java class. The model must match\n * with the type of the items returned by the service. For example, a\n * `PersonModel` can be used with a service that returns `Person` instances.\n *\n * By default, the grid shows columns for all properties of the model which\n * have a type that is supported. Use the `visibleColumns` option to customize\n * which columns to show and in which order.\n */\n model: DetachedModelConstructor<AbstractModel<TItem>>;\n /**\n * The property to use to detect an item's ID. The item ID is used to keep\n * the selection state when reloading the grid.\n *\n * By default, the component uses the property annotated with\n * `jakarta.persistence.Id`, or a property named `id`, in that order.\n * This option can be used to override the default behavior, or define the ID\n * property in case a class doesn't have a property matching the defaults.\n */\n itemIdProperty?: string;\n /**\n * Allows to provide a filter that is applied when fetching data from the\n * service. This can be used for implementing an external filter UI outside\n * the grid. A custom filter is not compatible with header filters.\n *\n * **NOTE:** This is considered an experimental feature and the API may change\n * in the future.\n */\n experimentalFilter?: FilterUnion;\n /**\n * Allows to customize which columns to show and in which order. This must be\n * an array of property names that are defined in the model. Nested properties\n * can be specified using dot notation, e.g. `address.street`.\n */\n visibleColumns?: string[];\n /**\n * Disables header filters, which are otherwise enabled by default.\n */\n noHeaderFilters?: boolean;\n /**\n * Allows to add custom columns to the grid. This must be an array of\n * `GridColumn` component instances. Custom columns are added after the\n * auto-generated columns.\n */\n customColumns?: JSX.Element[];\n /**\n * Allows to customize the props for individual columns. This is an object\n * where the keys must be property names that are defined in the model, and\n * the values are props that are accepted by the `GridColumn` component.\n * Nested properties can be specified using dot notation, e.g.\n * `address.street`.\n */\n columnOptions?: Record<string, ColumnOptions>;\n /**\n * When enabled, inserts a column with row numbers at the beginning of the\n * grid.\n */\n rowNumbers?: boolean;\n /**\n * When enabled, shows the total count of items in the grid footer.\n * This requires the provided service to implement the CountService interface,\n * otherwise an error will be logged to the console, without any count being\n * rendered.\n */\n totalCount?: boolean;\n /**\n * When enabled, shows the filtered item count in the grid footer.\n * if totalCount is also enabled, it will show both totalCount and filteredCount.\n * This requires the provided service to implement the CountService interface,\n * otherwise an error will be logged to the console, without any count being\n * rendered.\n */\n filteredCount?: boolean;\n /**\n * Allows to customize the grid footer with a custom renderer component for\n * the total count and filtered item count.\n * This requires the provided service to implement the CountService interface,\n * See {@link AutoGrid#totalCount} and {@link AutoGrid#filteredCount}.\n */\n footerCountRenderer?: ComponentType<ItemCounts>;\n}\n\nexport type AutoGridProps<TItem> = GridProps<TItem> & Readonly<AutoGridOwnProps<TItem>>;\n\ninterface ColumnConfigurationOptions {\n visibleColumns?: string[];\n noHeaderFilters?: boolean;\n customColumns?: JSX.Element[];\n columnOptions?: Record<string, ColumnOptions>;\n rowNumbers?: boolean;\n totalCount?: boolean;\n filteredCount?: boolean;\n footerCountRenderer?: ComponentType<ItemCounts>;\n itemCounts?: ItemCounts;\n}\n\nfunction wrapCustomColumn(\n column: JSX.Element,\n setColumnFilter: (filter: FilterUnion, filterKey: string) => void,\n options: ColumnConfigurationOptions,\n) {\n const key = column.key ?? 'no-key';\n const { header, headerRenderer } = column.props;\n const customOptions = options.columnOptions?.[key];\n const { header: customHeader, headerRenderer: customHeaderRenderer, headerFilterRenderer } = customOptions ?? {};\n const columnWithoutHeader = cloneElement(column, {\n header: null,\n headerRenderer: HeaderFilterWrapper,\n });\n return (\n <CustomColumnContext.Provider\n key={key}\n value={{\n setColumnFilter,\n headerFilterRenderer: headerFilterRenderer ?? NoHeaderFilter,\n filterKey: key,\n }}\n >\n <GridColumnGroup\n key={key}\n header={customHeader ?? header}\n headerRenderer={customHeaderRenderer ?? headerRenderer}\n >\n {columnWithoutHeader}\n </GridColumnGroup>\n </CustomColumnContext.Provider>\n );\n}\n\nfunction addCustomColumns(\n columns: JSX.Element[],\n options: ColumnConfigurationOptions,\n setColumnFilter: (filter: FilterUnion, filterKey: string) => void,\n): JSX.Element[] {\n if (!options.customColumns) {\n return columns;\n }\n\n // When using header filters, wrap custom columns into column groups and\n // move header text or renderer to group\n const customColumns = options.noHeaderFilters\n ? options.customColumns\n : options.customColumns.map((column) => wrapCustomColumn(column, setColumnFilter, options));\n\n // When using a custom column order, insert custom columns into auto-generated\n // ones using their `key`\n if (options.visibleColumns) {\n const columnMap = [...columns, ...customColumns].reduce((map, column) => {\n const { key } = column;\n if (key) {\n map.set(key, column);\n }\n return map;\n }, new Map<string, JSX.Element>());\n\n return options.visibleColumns.map((path) => columnMap.get(path)).filter(Boolean) as JSX.Element[];\n }\n\n // Otherwise just append custom columns at the end\n return [...columns, ...customColumns];\n}\n\nfunction useColumns(\n properties: PropertyInfo[],\n setColumnFilter: (filter: FilterUnion, filterKey: string) => void,\n options: ColumnConfigurationOptions,\n) {\n const sortableProperties = properties.filter(\n (propertyInfo) => options.columnOptions?.[propertyInfo.name]?.sortable !== false,\n );\n const [sortState, setSortState] = useState<SortState>(\n sortableProperties.length > 0 ? { [sortableProperties[0].name]: { direction: 'asc' } } : {},\n );\n let columns = properties.map((propertyInfo) => {\n let column;\n const customColumnOptions = options.columnOptions?.[propertyInfo.name];\n\n const { headerFilterRenderer, ...columnProps } = getColumnOptions(propertyInfo, customColumnOptions);\n\n if (!options.noHeaderFilters) {\n column = (\n <GridColumnGroup headerRenderer={HeaderSorter}>\n <GridColumn path={propertyInfo.name} headerRenderer={HeaderFilterWrapper} {...columnProps}></GridColumn>\n </GridColumnGroup>\n );\n } else {\n column = <GridColumn path={propertyInfo.name} headerRenderer={HeaderSorter} {...columnProps}></GridColumn>;\n }\n return (\n <ColumnContext.Provider\n key={propertyInfo.name}\n value={{\n propertyInfo,\n setColumnFilter,\n sortState,\n setSortState,\n customColumnOptions,\n headerFilterRenderer: headerFilterRenderer ?? NoHeaderFilter,\n filterKey: propertyInfo.name,\n }}\n >\n {column}\n </ColumnContext.Provider>\n );\n });\n\n columns = addCustomColumns(columns, options, setColumnFilter);\n\n if (options.rowNumbers) {\n columns = [\n <GridColumn key=\"rownumbers\" width=\"4em\" flexGrow={0} renderer={AutoGridRowNumberRenderer}></GridColumn>,\n ...columns,\n ];\n }\n const { totalCount, filteredCount, itemCounts, footerCountRenderer } = options;\n if (totalCount ?? filteredCount) {\n const col = (\n <FooterContext.Provider\n key=\"grid-footer\"\n value={{\n totalCount,\n filteredCount,\n footerCountRenderer,\n itemCounts,\n }}\n >\n <GridColumnGroup footerRenderer={AutoGridFooterItemCountRenderer}>{columns}</GridColumnGroup>\n </FooterContext.Provider>\n );\n columns = [col];\n }\n\n return columns;\n}\n\nfunction AutoGridInner<TItem>(\n {\n service,\n model,\n itemIdProperty,\n experimentalFilter,\n visibleColumns,\n noHeaderFilters,\n customColumns,\n columnOptions,\n rowNumbers,\n totalCount,\n filteredCount,\n footerCountRenderer,\n ...gridProps\n }: AutoGridProps<TItem>,\n ref: ForwardedRef<AutoGridRef<TItem>>,\n): JSX.Element {\n const [internalFilter, setInternalFilter] = useState<AndFilter>({ '@type': 'and', children: [] });\n const [itemCounts, setItemCounts] = useState<ItemCounts | undefined>();\n const gridRef = useRef<GridElement<TItem>>(null);\n const dataProviderRef = useRef<DataProvider<TItem>>();\n\n useImperativeHandle(\n ref,\n () => ({\n get grid() {\n return gridRef.current;\n },\n refresh() {\n dataProviderRef.current?.reset();\n gridRef.current?.clearCache();\n },\n }),\n [],\n );\n\n const setHeaderFilter = (filter: FilterUnion, filterKey: string) => {\n let changed = false;\n filter.key = filterKey;\n const indexOfFilter = filterKey\n ? internalFilter.children.findIndex((f) => (f as FilterUnion).key === filterKey)\n : -1;\n const isEmptyFilter = isFilterEmpty(filter);\n\n if (indexOfFilter >= 0 && isEmptyFilter) {\n internalFilter.children.splice(indexOfFilter, 1);\n changed = true;\n } else if (!isEmptyFilter) {\n if (indexOfFilter >= 0) {\n internalFilter.children[indexOfFilter] = filter;\n changed = true;\n } else {\n internalFilter.children.push(filter);\n changed = true;\n }\n }\n if (changed) {\n setInternalFilter({ ...internalFilter });\n }\n };\n\n const modelInfo = useMemo(() => new ModelInfo(model, itemIdProperty), [model]);\n const properties = visibleColumns ? modelInfo.getProperties(visibleColumns) : getDefaultProperties(modelInfo);\n const children = useColumns(properties, setHeaderFilter, {\n visibleColumns,\n noHeaderFilters,\n customColumns,\n columnOptions,\n rowNumbers,\n totalCount,\n filteredCount,\n footerCountRenderer,\n itemCounts,\n });\n\n useEffect(() => {\n // Remove all filtering if header filters are removed\n if (noHeaderFilters) {\n setInternalFilter({ '@type': 'and', children: [] });\n }\n }, [noHeaderFilters]);\n\n useEffect(() => {\n // Log an error if totalCount or filteredCount is enabled but the service doesn't implement CountService\n if ((!isCountService(service) && totalCount) ?? filteredCount) {\n console.error(\n '\"totalCount\" and \"filteredCount\" props require the provided service to implement the CountService interface.',\n );\n }\n // Sets the data provider, should be done only once\n const grid = gridRef.current!;\n // Wait for the sorting headers to be rendered so that the sorting state is correct for the first data provider call\n const timeoutId = setTimeout(() => {\n let firstUpdate = true;\n const dataProvider = createDataProvider(service, {\n initialFilter: experimentalFilter ?? internalFilter,\n loadTotalCount: totalCount,\n afterLoad(newItemCounts: ItemCounts) {\n setItemCounts(newItemCounts);\n\n if (firstUpdate) {\n // Workaround for https://github.com/vaadin/react-components/issues/129\n firstUpdate = false;\n setTimeout(() => grid.recalculateColumnWidths(), 0);\n }\n },\n });\n dataProviderRef.current = dataProvider;\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n gridRef.current!.dataProvider = dataProvider.load.bind(dataProvider);\n }, 1);\n\n return () => clearTimeout(timeoutId);\n }, [model, service]);\n\n useEffect(() => {\n // Update the filtering, whenever the filter changes\n const dataProvider = dataProviderRef.current;\n const grid = gridRef.current;\n if (grid && dataProvider) {\n dataProvider.setFilter(experimentalFilter ?? internalFilter);\n grid.clearCache();\n }\n }, [experimentalFilter, internalFilter]);\n\n return (\n <Grid itemIdPath={modelInfo.idProperty?.name} {...gridProps} ref={gridRef}>\n {children}\n </Grid>\n );\n}\n\ntype AutoGrid = <TItem>(\n props: AutoGridProps<TItem> & { ref?: ForwardedRef<AutoGridRef<TItem>> },\n) => ReturnType<typeof AutoGridInner>;\n\n/**\n * Auto Grid is a component for displaying tabular data based on a Java backend\n * service. It automatically generates columns based on the properties of a\n * Java class and provides features such as lazy-loading, sorting and filtering.\n *\n * Example usage:\n * ```tsx\n * import { AutoGrid } from '@hilla/react-crud';\n * import PersonService from 'Frontend/generated/endpoints';\n * import PersonModel from 'Frontend/generated/com/example/application/Person';\n *\n * <AutoGrid service={PersonService} model={PersonModel} />\n * ```\n */\nexport const AutoGrid: AutoGrid = forwardRef(AutoGridInner) as AutoGrid;\n\nexport type { ColumnOptions, HeaderFilterRendererProps };\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,5 @@
1
- import type { GridDataProviderCallback, GridDataProviderParams, GridElement } from '@vaadin/react-components/Grid';
1
+ import type { GridDataProviderCallback, GridDataProviderParams } from '@vaadin/react-components/Grid';
2
+ import type { GridDataProvider } from '@vaadin/react-components/Grid';
2
3
  import type { CountService, ListService } from './crud';
3
4
  import type FilterUnion from './types/com/vaadin/hilla/crud/filter/FilterUnion';
4
5
  import type Sort from './types/com/vaadin/hilla/mappedtypes/Sort';
@@ -26,17 +27,16 @@ type DataProviderOptions = {
26
27
  };
27
28
  export declare function isCountService<TItem>(service: ListAndMaybeCountService<TItem>): service is ListAndCountService<TItem>;
28
29
  export declare abstract class DataProvider<TItem> {
29
- protected readonly grid: GridElement;
30
30
  protected readonly service: ListAndMaybeCountService<TItem>;
31
31
  protected readonly loadTotalCount?: boolean;
32
32
  protected readonly afterLoadCallback?: AfterLoadCallback;
33
33
  protected filter: FilterUnion | undefined;
34
34
  protected totalCount: number | undefined;
35
35
  protected filteredCount: number | undefined;
36
- constructor(grid: GridElement, service: ListAndMaybeCountService<TItem>, options?: DataProviderOptions);
37
- refresh(): void;
36
+ constructor(service: ListAndMaybeCountService<TItem>, options?: DataProviderOptions);
37
+ reset(): void;
38
38
  setFilter(filter: FilterUnion | undefined): void;
39
- protected load(params: GridDataProviderParams<TItem>, callback: GridDataProviderCallback<TItem>): Promise<void>;
39
+ load(params: GridDataProviderParams<TItem>, callback: GridDataProviderCallback<TItem>): Promise<void>;
40
40
  protected fetchPage(params: GridDataProviderParams<TItem>): Promise<DataPage<TItem>>;
41
41
  protected abstract fetchTotalCount(page: DataPage<TItem>): Promise<number | undefined> | number | undefined;
42
42
  protected abstract fetchFilteredCount(page: DataPage<TItem>): Promise<number | undefined> | number | undefined;
@@ -47,10 +47,15 @@ export declare class InfiniteDataProvider<TItem> extends DataProvider<TItem> {
47
47
  }
48
48
  export declare class FixedSizeDataProvider<TItem> extends DataProvider<TItem> {
49
49
  service: ListAndCountService<TItem>;
50
- constructor(grid: GridElement, service: ListAndMaybeCountService<TItem>, options?: DataProviderOptions);
50
+ constructor(service: ListAndMaybeCountService<TItem>, options?: DataProviderOptions);
51
51
  protected fetchTotalCount(): Promise<number | undefined>;
52
52
  protected fetchFilteredCount(): Promise<number | undefined>;
53
53
  }
54
- export declare function createDataProvider<TItem>(grid: GridElement, service: ListAndMaybeCountService<TItem>, options?: DataProviderOptions): DataProvider<TItem>;
54
+ export declare function createDataProvider<TItem>(service: ListAndMaybeCountService<TItem>, options?: DataProviderOptions): DataProvider<TItem>;
55
+ type UseDataProviderResult<TItem> = Readonly<{
56
+ dataProvider: GridDataProvider<TItem>;
57
+ refresh(): void;
58
+ }>;
59
+ export declare function useDataProvider<TItem>(service: ListAndMaybeCountService<TItem>, filter?: FilterUnion): UseDataProviderResult<TItem>;
55
60
  export {};
56
61
  //# sourceMappingURL=data-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-provider.d.ts","sourceRoot":"","sources":["src/data-provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-provider.d.ts","sourceRoot":"","sources":["src/data-provider.ts"],"names":[],"mappings":"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"}
package/data-provider.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { useMemo, useState } from "react";
1
2
  import Direction from "./types/org/springframework/data/domain/Sort/Direction";
2
3
  function createSort(params) {
3
4
  return {
@@ -12,29 +13,26 @@ function isCountService(service) {
12
13
  return !!service.count;
13
14
  }
14
15
  class DataProvider {
15
- grid;
16
16
  service;
17
17
  loadTotalCount;
18
18
  afterLoadCallback;
19
19
  filter;
20
20
  totalCount;
21
21
  filteredCount;
22
- constructor(grid, service, options = {}) {
23
- this.grid = grid;
22
+ constructor(service, options = {}) {
24
23
  this.service = service;
25
24
  this.filter = options.initialFilter;
26
25
  this.loadTotalCount = options.loadTotalCount;
27
26
  this.afterLoadCallback = options.afterLoad;
28
- this.grid.dataProvider = this.load.bind(this);
27
+ this.load = this.load.bind(this);
29
28
  }
30
- refresh() {
29
+ reset() {
31
30
  this.totalCount = void 0;
32
31
  this.filteredCount = void 0;
33
- this.grid.clearCache();
34
32
  }
35
33
  setFilter(filter) {
34
+ this.reset();
36
35
  this.filter = filter;
37
- this.refresh();
38
36
  }
39
37
  async load(params, callback) {
40
38
  const page = await this.fetchPage(params);
@@ -75,9 +73,8 @@ class InfiniteDataProvider extends DataProvider {
75
73
  let infiniteScrollingSize;
76
74
  if (items.length === pageSize) {
77
75
  infiniteScrollingSize = (pageNumber + 1) * pageSize + 1;
78
- const cacheSize = this.grid._dataProviderController.rootCache.size;
79
- if (cacheSize !== void 0 && infiniteScrollingSize < cacheSize) {
80
- infiniteScrollingSize = void 0;
76
+ if (this.filteredCount !== void 0 && infiniteScrollingSize < this.filteredCount) {
77
+ infiniteScrollingSize = this.filteredCount;
81
78
  }
82
79
  } else {
83
80
  infiniteScrollingSize = pageNumber * pageSize + items.length;
@@ -86,11 +83,11 @@ class InfiniteDataProvider extends DataProvider {
86
83
  }
87
84
  }
88
85
  class FixedSizeDataProvider extends DataProvider {
89
- constructor(grid, service, options = {}) {
86
+ constructor(service, options = {}) {
90
87
  if (!isCountService(service)) {
91
88
  throw new Error("The provided service does not implement the CountService interface.");
92
89
  }
93
- super(grid, service, options);
90
+ super(service, options);
94
91
  }
95
92
  async fetchTotalCount() {
96
93
  if (this.totalCount !== void 0) {
@@ -105,17 +102,32 @@ class FixedSizeDataProvider extends DataProvider {
105
102
  return this.service.count(this.filter);
106
103
  }
107
104
  }
108
- function createDataProvider(grid, service, options = {}) {
105
+ function createDataProvider(service, options = {}) {
109
106
  if (isCountService(service)) {
110
- return new FixedSizeDataProvider(grid, service, options);
107
+ return new FixedSizeDataProvider(service, options);
111
108
  }
112
- return new InfiniteDataProvider(grid, service, options);
109
+ return new InfiniteDataProvider(service, options);
110
+ }
111
+ function useDataProvider(service, filter) {
112
+ const [refreshCounter, setRefreshCounter] = useState(0);
113
+ const dataProvider = useMemo(() => createDataProvider(service, { initialFilter: filter }), [service]);
114
+ dataProvider.setFilter(filter);
115
+ const dataProviderFn = useMemo(() => dataProvider.load.bind(dataProvider), [dataProvider, filter, refreshCounter]);
116
+ return {
117
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
118
+ dataProvider: dataProviderFn,
119
+ refresh: () => {
120
+ dataProvider.reset();
121
+ setRefreshCounter(refreshCounter + 1);
122
+ }
123
+ };
113
124
  }
114
125
  export {
115
126
  DataProvider,
116
127
  FixedSizeDataProvider,
117
128
  InfiniteDataProvider,
118
129
  createDataProvider,
119
- isCountService
130
+ isCountService,
131
+ useDataProvider
120
132
  };
121
133
  //# sourceMappingURL=data-provider.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["src/data-provider.ts"],
4
- "sourcesContent": ["import type {\n GridDataProviderCallback,\n GridDataProviderParams,\n GridDefaultItem,\n GridElement,\n} from '@vaadin/react-components/Grid';\nimport type { CountService, ListService } from './crud';\nimport type FilterUnion from './types/com/vaadin/hilla/crud/filter/FilterUnion';\nimport type Sort from './types/com/vaadin/hilla/mappedtypes/Sort';\nimport Direction from './types/org/springframework/data/domain/Sort/Direction';\n\ntype GridElementWithInternalAPI<TItem = GridDefaultItem> = GridElement<TItem> &\n Readonly<{\n _dataProviderController: {\n rootCache: {\n size?: number;\n };\n };\n }>;\n\ntype MaybeCountService<TItem> = Partial<CountService<TItem>>;\ntype ListAndMaybeCountService<TItem> = ListService<TItem> & MaybeCountService<TItem>;\ntype ListAndCountService<TItem> = CountService<TItem> & ListService<TItem>;\n\ntype PageRequest = {\n pageNumber: number;\n pageSize: number;\n sort: Sort;\n};\n\ntype DataPage<TItem> = {\n items: TItem[];\n pageRequest: PageRequest;\n};\n\nexport type ItemCounts = {\n totalCount?: number;\n filteredCount?: number;\n};\n\ntype AfterLoadCallback = (result: ItemCounts) => void;\n\ntype DataProviderOptions = {\n initialFilter?: FilterUnion;\n loadTotalCount?: boolean;\n afterLoad?: AfterLoadCallback;\n};\n\nfunction createSort<TItem>(params: GridDataProviderParams<TItem>): Sort {\n return {\n orders: params.sortOrders\n .filter((order) => order.direction != null)\n .map((order) => ({\n property: order.path,\n direction: order.direction === 'asc' ? Direction.ASC : Direction.DESC,\n ignoreCase: false,\n })),\n };\n}\n\nexport function isCountService<TItem>(service: ListAndMaybeCountService<TItem>): service is ListAndCountService<TItem> {\n return !!service.count;\n}\n\nexport abstract class DataProvider<TItem> {\n protected readonly grid: GridElement;\n protected readonly service: ListAndMaybeCountService<TItem>;\n protected readonly loadTotalCount?: boolean;\n protected readonly afterLoadCallback?: AfterLoadCallback;\n\n protected filter: FilterUnion | undefined;\n protected totalCount: number | undefined;\n protected filteredCount: number | undefined;\n\n constructor(grid: GridElement, service: ListAndMaybeCountService<TItem>, options: DataProviderOptions = {}) {\n this.grid = grid;\n this.service = service;\n this.filter = options.initialFilter;\n this.loadTotalCount = options.loadTotalCount;\n this.afterLoadCallback = options.afterLoad;\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.grid.dataProvider = this.load.bind(this);\n }\n\n refresh(): void {\n this.totalCount = undefined;\n this.filteredCount = undefined;\n this.grid.clearCache();\n }\n\n setFilter(filter: FilterUnion | undefined): void {\n this.filter = filter;\n this.refresh();\n }\n\n protected async load(\n params: GridDataProviderParams<TItem>,\n callback: GridDataProviderCallback<TItem>,\n ): Promise<void> {\n // Fetch page and filtered count\n const page = await this.fetchPage(params);\n this.filteredCount = await this.fetchFilteredCount(page);\n // Only fetch total count if it's specific in options\n if (this.loadTotalCount) {\n this.totalCount = await this.fetchTotalCount(page);\n }\n\n // Pass results to grid\n callback(page.items, this.filteredCount);\n\n // Pass results to callback\n if (this.afterLoadCallback) {\n this.afterLoadCallback({\n totalCount: this.totalCount,\n filteredCount: this.filteredCount,\n });\n }\n }\n\n protected async fetchPage(params: GridDataProviderParams<TItem>): Promise<DataPage<TItem>> {\n const sort = createSort(params);\n const pageNumber = params.page;\n const { pageSize } = params;\n const pageRequest = {\n pageNumber,\n pageSize,\n sort,\n };\n const items = await this.service.list(pageRequest, this.filter);\n\n return { items, pageRequest };\n }\n\n protected abstract fetchTotalCount(page: DataPage<TItem>): Promise<number | undefined> | number | undefined;\n\n protected abstract fetchFilteredCount(page: DataPage<TItem>): Promise<number | undefined> | number | undefined;\n}\n\nexport class InfiniteDataProvider<TItem> extends DataProvider<TItem> {\n // cannot be static, otherwise it does not implement superclass\n // eslint-disable-next-line @typescript-eslint/class-methods-use-this\n protected fetchTotalCount(): undefined {\n return undefined;\n }\n\n protected fetchFilteredCount(page: DataPage<TItem>): number | undefined {\n const { items, pageRequest } = page;\n const { pageNumber, pageSize } = pageRequest;\n let infiniteScrollingSize;\n\n if (items.length === pageSize) {\n infiniteScrollingSize = (pageNumber + 1) * pageSize + 1;\n const cacheSize = (this.grid as GridElementWithInternalAPI<TItem>)._dataProviderController.rootCache.size;\n if (cacheSize !== undefined && infiniteScrollingSize < cacheSize) {\n // Only allow size to grow here to avoid shrinking the size when scrolled down and sorting\n infiniteScrollingSize = undefined;\n }\n } else {\n infiniteScrollingSize = pageNumber * pageSize + items.length;\n }\n\n return infiniteScrollingSize;\n }\n}\n\nexport class FixedSizeDataProvider<TItem> extends DataProvider<TItem> {\n declare service: ListAndCountService<TItem>;\n\n constructor(grid: GridElement, service: ListAndMaybeCountService<TItem>, options: DataProviderOptions = {}) {\n if (!isCountService(service)) {\n throw new Error('The provided service does not implement the CountService interface.');\n }\n super(grid, service, options);\n }\n\n protected async fetchTotalCount(): Promise<number | undefined> {\n // Use cached count if it's already known\n if (this.totalCount !== undefined) {\n return this.totalCount;\n }\n return this.service.count(undefined);\n }\n\n protected async fetchFilteredCount(): Promise<number | undefined> {\n // Use cached count if it's already known\n if (this.filteredCount !== undefined) {\n return this.filteredCount;\n }\n return this.service.count(this.filter);\n }\n}\n\nexport function createDataProvider<TItem>(\n grid: GridElement,\n service: ListAndMaybeCountService<TItem>,\n options: DataProviderOptions = {},\n): DataProvider<TItem> {\n if (isCountService(service)) {\n return new FixedSizeDataProvider(grid, service, options);\n }\n return new InfiniteDataProvider(grid, service, options);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { GridDataProviderCallback, GridDataProviderParams } from '@vaadin/react-components/Grid';\nimport type { GridDataProvider } from '@vaadin/react-components/Grid';\nimport { useMemo, useState } from 'react';\nimport type { CountService, ListService } from './crud';\nimport type FilterUnion from './types/com/vaadin/hilla/crud/filter/FilterUnion';\nimport type Sort from './types/com/vaadin/hilla/mappedtypes/Sort';\nimport Direction from './types/org/springframework/data/domain/Sort/Direction';\n\ntype MaybeCountService<TItem> = Partial<CountService<TItem>>;\ntype ListAndMaybeCountService<TItem> = ListService<TItem> & MaybeCountService<TItem>;\ntype ListAndCountService<TItem> = CountService<TItem> & ListService<TItem>;\n\ntype PageRequest = {\n pageNumber: number;\n pageSize: number;\n sort: Sort;\n};\n\ntype DataPage<TItem> = {\n items: TItem[];\n pageRequest: PageRequest;\n};\n\nexport type ItemCounts = {\n totalCount?: number;\n filteredCount?: number;\n};\n\ntype AfterLoadCallback = (result: ItemCounts) => void;\n\ntype DataProviderOptions = {\n initialFilter?: FilterUnion;\n loadTotalCount?: boolean;\n afterLoad?: AfterLoadCallback;\n};\n\nfunction createSort<TItem>(params: GridDataProviderParams<TItem>): Sort {\n return {\n orders: params.sortOrders\n .filter((order) => order.direction != null)\n .map((order) => ({\n property: order.path,\n direction: order.direction === 'asc' ? Direction.ASC : Direction.DESC,\n ignoreCase: false,\n })),\n };\n}\n\nexport function isCountService<TItem>(service: ListAndMaybeCountService<TItem>): service is ListAndCountService<TItem> {\n return !!service.count;\n}\n\nexport abstract class DataProvider<TItem> {\n protected readonly service: ListAndMaybeCountService<TItem>;\n protected readonly loadTotalCount?: boolean;\n protected readonly afterLoadCallback?: AfterLoadCallback;\n\n protected filter: FilterUnion | undefined;\n protected totalCount: number | undefined;\n protected filteredCount: number | undefined;\n\n constructor(service: ListAndMaybeCountService<TItem>, options: DataProviderOptions = {}) {\n this.service = service;\n this.filter = options.initialFilter;\n this.loadTotalCount = options.loadTotalCount;\n this.afterLoadCallback = options.afterLoad;\n\n this.load = this.load.bind(this);\n }\n\n reset(): void {\n this.totalCount = undefined;\n this.filteredCount = undefined;\n }\n\n setFilter(filter: FilterUnion | undefined): void {\n this.reset();\n this.filter = filter;\n }\n\n async load(params: GridDataProviderParams<TItem>, callback: GridDataProviderCallback<TItem>): Promise<void> {\n // Fetch page and filtered count\n const page = await this.fetchPage(params);\n this.filteredCount = await this.fetchFilteredCount(page);\n // Only fetch total count if it's specific in options\n if (this.loadTotalCount) {\n this.totalCount = await this.fetchTotalCount(page);\n }\n\n // Pass results to grid\n callback(page.items, this.filteredCount);\n\n // Pass results to callback\n if (this.afterLoadCallback) {\n this.afterLoadCallback({\n totalCount: this.totalCount,\n filteredCount: this.filteredCount,\n });\n }\n }\n\n protected async fetchPage(params: GridDataProviderParams<TItem>): Promise<DataPage<TItem>> {\n const sort = createSort(params);\n const pageNumber = params.page;\n const { pageSize } = params;\n const pageRequest = {\n pageNumber,\n pageSize,\n sort,\n };\n const items = await this.service.list(pageRequest, this.filter);\n\n return { items, pageRequest };\n }\n\n protected abstract fetchTotalCount(page: DataPage<TItem>): Promise<number | undefined> | number | undefined;\n\n protected abstract fetchFilteredCount(page: DataPage<TItem>): Promise<number | undefined> | number | undefined;\n}\n\nexport class InfiniteDataProvider<TItem> extends DataProvider<TItem> {\n // cannot be static, otherwise it does not implement superclass\n // eslint-disable-next-line @typescript-eslint/class-methods-use-this\n protected fetchTotalCount(): undefined {\n return undefined;\n }\n\n protected fetchFilteredCount(page: DataPage<TItem>): number | undefined {\n const { items, pageRequest } = page;\n const { pageNumber, pageSize } = pageRequest;\n let infiniteScrollingSize;\n\n if (items.length === pageSize) {\n infiniteScrollingSize = (pageNumber + 1) * pageSize + 1;\n if (this.filteredCount !== undefined && infiniteScrollingSize < this.filteredCount) {\n // Only allow size to grow here to avoid shrinking the size when scrolled down and sorting\n infiniteScrollingSize = this.filteredCount;\n }\n } else {\n infiniteScrollingSize = pageNumber * pageSize + items.length;\n }\n\n return infiniteScrollingSize;\n }\n}\n\nexport class FixedSizeDataProvider<TItem> extends DataProvider<TItem> {\n declare service: ListAndCountService<TItem>;\n\n constructor(service: ListAndMaybeCountService<TItem>, options: DataProviderOptions = {}) {\n if (!isCountService(service)) {\n throw new Error('The provided service does not implement the CountService interface.');\n }\n super(service, options);\n }\n\n protected async fetchTotalCount(): Promise<number | undefined> {\n // Use cached count if it's already known\n if (this.totalCount !== undefined) {\n return this.totalCount;\n }\n return this.service.count(undefined);\n }\n\n protected async fetchFilteredCount(): Promise<number | undefined> {\n // Use cached count if it's already known\n if (this.filteredCount !== undefined) {\n return this.filteredCount;\n }\n return this.service.count(this.filter);\n }\n}\n\nexport function createDataProvider<TItem>(\n service: ListAndMaybeCountService<TItem>,\n options: DataProviderOptions = {},\n): DataProvider<TItem> {\n if (isCountService(service)) {\n return new FixedSizeDataProvider(service, options);\n }\n return new InfiniteDataProvider(service, options);\n}\n\ntype UseDataProviderResult<TItem> = Readonly<{\n dataProvider: GridDataProvider<TItem>;\n refresh(): void;\n}>;\n\nexport function useDataProvider<TItem>(\n service: ListAndMaybeCountService<TItem>,\n filter?: FilterUnion,\n): UseDataProviderResult<TItem> {\n const [refreshCounter, setRefreshCounter] = useState(0);\n const dataProvider = useMemo(() => createDataProvider(service, { initialFilter: filter }), [service]);\n\n // Update filter in data provider\n dataProvider.setFilter(filter);\n\n // Create a new data provider function reference when the filter changes or the refresh counter is incremented.\n // This effectively forces the grid to reload\n const dataProviderFn = useMemo(() => dataProvider.load.bind(dataProvider), [dataProvider, filter, refreshCounter]);\n\n return {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n dataProvider: dataProviderFn,\n refresh: () => {\n dataProvider.reset();\n setRefreshCounter(refreshCounter + 1);\n },\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/index.d.ts CHANGED
@@ -2,4 +2,5 @@ export * from './autogrid-feature.js';
2
2
  export type * from './crud.js';
3
3
  export * from './autoform-feature.js';
4
4
  export * from './autocrud-feature.js';
5
+ export { useDataProvider } from './data-provider.js';
5
6
  //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,mBAAmB,WAAW,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,mBAAmB,WAAW,CAAC;AAC/B,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
package/index.js CHANGED
@@ -3,11 +3,15 @@ function __REGISTER__(feature) {
3
3
  window.Vaadin.registrations ??= [];
4
4
  window.Vaadin.registrations.push({
5
5
  is: feature ? `${"@vaadin/hilla-react-crud"}/${feature}` : "@vaadin/hilla-react-crud",
6
- version: "24.4.0-alpha2"
6
+ version: "24.4.0-alpha3"
7
7
  });
8
8
  }
9
9
  export * from "./autogrid-feature.js";
10
10
  export * from "./autoform-feature.js";
11
11
  export * from "./autocrud-feature.js";
12
+ import { useDataProvider } from "./data-provider.js";
12
13
  __REGISTER__();
14
+ export {
15
+ useDataProvider
16
+ };
13
17
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../scripts/register.js", "src/index.ts"],
4
- "sourcesContent": ["export function __REGISTER__(feature) {\n window.Vaadin ??= {};\n window.Vaadin.registrations ??= [];\n window.Vaadin.registrations.push({\n is: feature ? `${__NAME__}/${feature}` : __NAME__,\n version: __VERSION__,\n });\n}\n", "export * from './autogrid-feature.js';\nexport type * from './crud.js';\nexport * from './autoform-feature.js';\nexport * from './autocrud-feature.js';\n\n// @ts-expect-error: esbuild injection\n// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n__REGISTER__();\n"],
5
- "mappings": "AAAO,SAAS,aAAa,SAAS;AACpC,SAAO,WAAW,CAAC;AACnB,SAAO,OAAO,kBAAkB,CAAC;AACjC,SAAO,OAAO,cAAc,KAAK;AAAA,IAC/B,IAAI,UAAU,GAAG,0BAAQ,IAAI,OAAO,KAAK;AAAA,IACzC,SAAS;AAAA,EACX,CAAC;AACH;ACPA,cAAc;AAEd,cAAc;AACd,cAAc;AAId,aAAa;",
4
+ "sourcesContent": ["export function __REGISTER__(feature) {\n window.Vaadin ??= {};\n window.Vaadin.registrations ??= [];\n window.Vaadin.registrations.push({\n is: feature ? `${__NAME__}/${feature}` : __NAME__,\n version: __VERSION__,\n });\n}\n", "export * from './autogrid-feature.js';\nexport type * from './crud.js';\nexport * from './autoform-feature.js';\nexport * from './autocrud-feature.js';\nexport { useDataProvider } from './data-provider.js';\n\n// @ts-expect-error: esbuild injection\n// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n__REGISTER__();\n"],
5
+ "mappings": "AAAO,SAAS,aAAa,SAAS;AACpC,SAAO,WAAW,CAAC;AACnB,SAAO,OAAO,kBAAkB,CAAC;AACjC,SAAO,OAAO,cAAc,KAAK;AAAA,IAC/B,IAAI,UAAU,GAAG,0BAAQ,IAAI,OAAO,KAAK;AAAA,IACzC,SAAS;AAAA,EACX,CAAC;AACH;ACPA,cAAc;AAEd,cAAc;AACd,cAAc;AACd,SAAS,uBAAuB;AAIhC,aAAa;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/hilla-react-crud",
3
- "version": "24.4.0-alpha2",
3
+ "version": "24.4.0-alpha3",
4
4
  "description": "Hilla CRUD utils for React",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -56,11 +56,10 @@
56
56
  "access": "public"
57
57
  },
58
58
  "dependencies": {
59
- "@vaadin/hilla-lit-form": "24.4.0-alpha2",
60
- "@vaadin/hilla-core": "24.4.0-alpha2",
61
- "@vaadin/react-components": "^24.4.0-alpha3",
62
- "@vaadin/hilla-react-form": "24.4.0-alpha2",
63
- "@vaadin/vaadin-lumo-styles": "~24.4.0-alpha3"
59
+ "@vaadin/hilla-core": "24.4.0-alpha3",
60
+ "@vaadin/hilla-lit-form": "24.4.0-alpha3",
61
+ "@vaadin/hilla-react-form": "24.4.0-alpha3",
62
+ "@vaadin/react-components": "24.4.0-alpha10"
64
63
  },
65
64
  "peerDependencies": {
66
65
  "react": "^18"
package/util.js CHANGED
@@ -3,7 +3,7 @@ function __REGISTER__(feature) {
3
3
  window.Vaadin.registrations ??= [];
4
4
  window.Vaadin.registrations.push({
5
5
  is: feature ? `${"@vaadin/hilla-react-crud"}/${feature}` : "@vaadin/hilla-react-crud",
6
- version: "24.4.0-alpha2"
6
+ version: "24.4.0-alpha3"
7
7
  });
8
8
  }
9
9
  import { jsx } from "react/jsx-runtime";