@vaadin/hilla-react-crud 24.8.0-alpha1 → 24.8.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 CHANGED
@@ -13,8 +13,8 @@ export type AutoCrudProps<TModel extends AbstractModel = AbstractModel> = Compon
13
13
  service: CrudService<Value<TModel>>;
14
14
  model: DetachedModelConstructor<TModel>;
15
15
  itemIdProperty?: string;
16
- newButton?: boolean;
16
+ noNewButton?: boolean;
17
17
  formProps?: AutoCrudFormProps<TModel>;
18
18
  gridProps?: AutoCrudGridProps<Value<TModel>>;
19
19
  }>;
20
- export declare function AutoCrud<TModel extends AbstractModel>({ service, model, itemIdProperty, newButton, formProps, gridProps, style, id, className, }: AutoCrudProps<TModel>): JSX.Element;
20
+ export declare function AutoCrud<TModel extends AbstractModel>({ service, model, itemIdProperty, noNewButton, formProps, gridProps, style, id, className, }: AutoCrudProps<TModel>): JSX.Element;
package/autocrud.js CHANGED
@@ -13,7 +13,7 @@ function defaultFormHeaderRenderer(editedItem, disabled) {
13
13
  const style = { color: disabled ? 'var(--lumo-disabled-text-color)' : 'var(--lumo-text-color)' };
14
14
  return editedItem ? _jsx("h3", { style: style, children: "Edit item" }) : _jsx("h3", { style: style, children: "New item" });
15
15
  }
16
- export function AutoCrud({ service, model, itemIdProperty, newButton, formProps, gridProps, style, id, className, }) {
16
+ export function AutoCrud({ service, model, itemIdProperty, noNewButton, formProps, gridProps, style, id, className, }) {
17
17
  const [item, setItem] = useState(undefined);
18
18
  const fullScreen = useMediaQuery('(max-width: 600px), (max-height: 600px)');
19
19
  const autoGridRef = useRef(null);
@@ -30,7 +30,7 @@ export function AutoCrud({ service, model, itemIdProperty, newButton, formProps,
30
30
  const mainSection = (_jsxs("div", { className: "auto-crud-main", children: [_jsx(AutoGrid, { ...gridProps, service: service, model: model, itemIdProperty: itemIdProperty, selectedItems: item && item !== emptyItem ? [item] : [], onActiveItemChanged: (e) => {
31
31
  const activeItem = e.detail.value;
32
32
  setItem(activeItem ?? undefined);
33
- }, ref: autoGridRef, "aria-controls": autoFormProps.id ?? `auto-form-${id ?? autoCrudId}` }), newButton !== false && (_jsx("div", { className: "auto-crud-toolbar", children: _jsx(Button, { theme: "primary", onClick: () => setItem(emptyItem), children: "+ New" }) }))] }));
33
+ }, ref: autoGridRef, "aria-controls": autoFormProps.id ?? `auto-form-${id ?? autoCrudId}` }), !noNewButton && (_jsx("div", { className: "auto-crud-toolbar", children: _jsx(Button, { theme: "primary", onClick: () => setItem(emptyItem), children: "+ New" }) }))] }));
34
34
  const autoForm = (_jsx(AutoForm, { id: autoFormProps.id ?? `auto-form-${id ?? autoCrudId}`, deleteButtonVisible: true, ...autoFormProps, disabled: !item, service: service, model: model, itemIdProperty: itemIdProperty, item: item, onSubmitSuccess: ({ item: submittedItem }) => {
35
35
  if (fullScreen) {
36
36
  setItem(undefined);
@@ -43,6 +43,6 @@ export function AutoCrud({ service, model, itemIdProperty, newButton, formProps,
43
43
  setItem(undefined);
44
44
  refreshGrid();
45
45
  } }));
46
- return (_jsx("div", { className: `auto-crud ${className ?? ''}`, id: id, style: style, children: fullScreen ? (_jsxs(_Fragment, { children: [mainSection, _jsx(AutoCrudDialog, { opened: !!item, header: formHeader, onClose: handleCancel, children: autoForm })] })) : (_jsxs(SplitLayout, { theme: "small", children: [mainSection, _jsxs("div", { className: "auto-crud-form", children: [_jsx("div", { className: "auto-crud-form-header", children: formHeader }), autoForm] })] })) }));
46
+ return (_jsx("div", { className: `auto-crud ${className ?? ''}`, id: id, style: style, children: noNewButton && (!item || item === emptyItem) ? (mainSection) : fullScreen ? (_jsxs(_Fragment, { children: [mainSection, _jsx(AutoCrudDialog, { opened: !!item, header: formHeader, onClose: handleCancel, children: autoForm })] })) : (_jsxs(SplitLayout, { theme: "small", children: [mainSection, _jsxs("div", { className: "auto-crud-form", children: [_jsx("div", { className: "auto-crud-form-header", children: formHeader }), autoForm] })] })) }));
47
47
  }
48
48
  //# sourceMappingURL=autocrud.js.map
package/autocrud.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"autocrud.js","sourceRoot":"","sources":["src/autocrud.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAY,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,GAAG,MAAM,mBAAmB,CAAC;AACpC,OAAO,EAAsB,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAsB,QAAQ,EAAoB,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAA4B,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEzE,kBAAkB,CAAC,GAAG,CAAC,CAAC;AAqFxB,SAAS,yBAAyB,CAAQ,UAAwB,EAAE,QAAiB;IACnF,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,wBAAwB,EAAE,CAAC;IACjG,OAAO,UAAU,CAAC,CAAC,CAAC,aAAI,KAAK,EAAE,KAAK,0BAAgB,CAAC,CAAC,CAAC,aAAI,KAAK,EAAE,KAAK,yBAAe,CAAC;AACzF,CAAC;AAiBD,MAAM,UAAU,QAAQ,CAA+B,EACrD,OAAO,EACP,KAAK,EACL,cAAc,EACd,SAAS,EACT,SAAS,EACT,SAAS,EACT,KAAK,EACL,EAAE,EACF,SAAS,GACa;IACtB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAA+C,SAAS,CAAC,CAAC;IAC1F,MAAM,UAAU,GAAG,aAAa,CAAC,yCAAyC,CAAC,CAAC;IAC5E,MAAM,WAAW,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IAC9C,MAAM,EAAE,cAAc,EAAE,wBAAwB,EAAE,GAAG,aAAa,EAAE,GAAG,SAAS,IAAI,EAAE,CAAC;IACvF,MAAM,kBAAkB,GACtB,wBAAwB,IAAI,yBAAyB,CAAC;IAExD,MAAM,UAAU,GAAG,KAAK,EAAE,CAAC;IAE3B,SAAS,WAAW;QAClB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;IACjC,CAAC;IAED,SAAS,YAAY;QACnB,OAAO,CAAC,SAAS,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;IAElH,MAAM,WAAW,GAAG,CAClB,eAAK,SAAS,EAAC,gBAAgB,aAC7B,KAAC,QAAQ,OACH,SAAS,EACb,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAA+D,EACtE,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,IAAI,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EACvD,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE;oBACzB,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;oBAClC,OAAO,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC;gBACnC,CAAC,EACD,GAAG,EAAE,WAAW,mBACD,aAAa,CAAC,EAAE,IAAI,aAAa,EAAE,IAAI,UAAU,EAAE,GACxD,EAGX,SAAS,KAAK,KAAK,IAAI,CACtB,cAAK,SAAS,EAAC,mBAAmB,YAChC,KAAC,MAAM,IAAC,KAAK,EAAC,SAAS,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,sBAEhD,GACL,CACP,IACG,CACP,CAAC;IAEF,MAAM,QAAQ,GAAG,CACf,KAAC,QAAQ,IACP,EAAE,EAAE,aAAa,CAAC,EAAE,IAAI,aAAa,EAAE,IAAI,UAAU,EAAE,EACvD,mBAAmB,EAAE,IAAI,KACrB,aAAa,EACjB,QAAQ,EAAE,CAAC,IAAI,EACf,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,EACZ,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE;YAC3C,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,CAAC,SAAS,CAAC,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,aAAa,CAAC,CAAC;YACzB,CAAC;YACD,WAAW,EAAE,CAAC;QAChB,CAAC,EACD,eAAe,EAAE,GAAG,EAAE;YACpB,OAAO,CAAC,SAAS,CAAC,CAAC;YACnB,WAAW,EAAE,CAAC;QAChB,CAAC,GACD,CACH,CAAC;IAEF,OAAO,CACL,cAAK,SAAS,EAAE,aAAa,SAAS,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,YACjE,UAAU,CAAC,CAAC,CAAC,CACZ,8BACG,WAAW,EACZ,KAAC,cAAc,IAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,YACtE,QAAQ,GACM,IAChB,CACJ,CAAC,CAAC,CAAC,CACF,MAAC,WAAW,IAAC,KAAK,EAAC,OAAO,aACvB,WAAW,EACZ,eAAK,SAAS,EAAC,gBAAgB,aAC7B,cAAK,SAAS,EAAC,uBAAuB,YAAE,UAAU,GAAO,EACxD,QAAQ,IACL,IACM,CACf,GACG,CACP,CAAC;AACJ,CAAC","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 * Determines whether to display the \"New\" button in the toolbar. By default,\n * this is set to `true`, meaning the button will be shown.\n *\n * NOTE: This setting only hides the button; it does not prevent new items\n * from being sent to the service. Ensure your backend Java service is\n * properly secured to prevent unauthorized creation of new items.\n */\n newButton?: boolean;\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 newButton,\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 {/* As the toolbar only contains the \"New\" button at the moment, and as an empty toolbar\n renders as a half-height bar, let's hide it completely when the button is hidden */}\n {newButton !== false && (\n <div className=\"auto-crud-toolbar\">\n <Button theme=\"primary\" onClick={() => setItem(emptyItem)}>\n + New\n </Button>\n </div>\n )}\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"]}
1
+ {"version":3,"file":"autocrud.js","sourceRoot":"","sources":["src/autocrud.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAY,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,GAAG,MAAM,mBAAmB,CAAC;AACpC,OAAO,EAAsB,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,EAAsB,QAAQ,EAAoB,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAA4B,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEzE,kBAAkB,CAAC,GAAG,CAAC,CAAC;AAsFxB,SAAS,yBAAyB,CAAQ,UAAwB,EAAE,QAAiB;IACnF,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,wBAAwB,EAAE,CAAC;IACjG,OAAO,UAAU,CAAC,CAAC,CAAC,aAAI,KAAK,EAAE,KAAK,0BAAgB,CAAC,CAAC,CAAC,aAAI,KAAK,EAAE,KAAK,yBAAe,CAAC;AACzF,CAAC;AAiBD,MAAM,UAAU,QAAQ,CAA+B,EACrD,OAAO,EACP,KAAK,EACL,cAAc,EACd,WAAW,EACX,SAAS,EACT,SAAS,EACT,KAAK,EACL,EAAE,EACF,SAAS,GACa;IACtB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAA+C,SAAS,CAAC,CAAC;IAC1F,MAAM,UAAU,GAAG,aAAa,CAAC,yCAAyC,CAAC,CAAC;IAC5E,MAAM,WAAW,GAAG,MAAM,CAAc,IAAI,CAAC,CAAC;IAC9C,MAAM,EAAE,cAAc,EAAE,wBAAwB,EAAE,GAAG,aAAa,EAAE,GAAG,SAAS,IAAI,EAAE,CAAC;IACvF,MAAM,kBAAkB,GACtB,wBAAwB,IAAI,yBAAyB,CAAC;IAExD,MAAM,UAAU,GAAG,KAAK,EAAE,CAAC;IAE3B,SAAS,WAAW;QAClB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;IACjC,CAAC;IAED,SAAS,YAAY;QACnB,OAAO,CAAC,SAAS,CAAC,CAAC;IACrB,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC;IAElH,MAAM,WAAW,GAAG,CAClB,eAAK,SAAS,EAAC,gBAAgB,aAC7B,KAAC,QAAQ,OACH,SAAS,EACb,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAA+D,EACtE,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,IAAI,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EACvD,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE;oBACzB,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;oBAClC,OAAO,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC;gBACnC,CAAC,EACD,GAAG,EAAE,WAAW,mBACD,aAAa,CAAC,EAAE,IAAI,aAAa,EAAE,IAAI,UAAU,EAAE,GACxD,EAGX,CAAC,WAAW,IAAI,CACf,cAAK,SAAS,EAAC,mBAAmB,YAChC,KAAC,MAAM,IAAC,KAAK,EAAC,SAAS,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,sBAEhD,GACL,CACP,IACG,CACP,CAAC;IAEF,MAAM,QAAQ,GAAG,CACf,KAAC,QAAQ,IACP,EAAE,EAAE,aAAa,CAAC,EAAE,IAAI,aAAa,EAAE,IAAI,UAAU,EAAE,EACvD,mBAAmB,EAAE,IAAI,KACrB,aAAa,EACjB,QAAQ,EAAE,CAAC,IAAI,EACf,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,EACZ,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,IAAI,EACV,eAAe,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE;YAC3C,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,CAAC,SAAS,CAAC,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,aAAa,CAAC,CAAC;YACzB,CAAC;YACD,WAAW,EAAE,CAAC;QAChB,CAAC,EACD,eAAe,EAAE,GAAG,EAAE;YACpB,OAAO,CAAC,SAAS,CAAC,CAAC;YACnB,WAAW,EAAE,CAAC;QAChB,CAAC,GACD,CACH,CAAC;IAIF,OAAO,CACL,cAAK,SAAS,EAAE,aAAa,SAAS,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,YACjE,WAAW,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAC9C,WAAW,CACZ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CACf,8BACG,WAAW,EACZ,KAAC,cAAc,IAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,YACtE,QAAQ,GACM,IAChB,CACJ,CAAC,CAAC,CAAC,CACF,MAAC,WAAW,IAAC,KAAK,EAAC,OAAO,aACvB,WAAW,EACZ,eAAK,SAAS,EAAC,gBAAgB,aAC7B,cAAK,SAAS,EAAC,uBAAuB,YAAE,UAAU,GAAO,EACxD,QAAQ,IACL,IACM,CACf,GACG,CACP,CAAC;AACJ,CAAC","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 * Determines whether to hide the \"New\" button in the toolbar.\n *\n * NOTE: This setting only hides the button; it does not prevent new items\n * from being sent to the service. Ensure your backend Java service is\n * properly secured to prevent unauthorized creation of new items.\n *\n * @defaultValue `false` meaning the button will be shown.\n */\n noNewButton?: boolean;\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 noNewButton,\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 {/* As the toolbar only contains the \"New\" button at the moment, and as an empty toolbar\n renders as a half-height bar, let's hide it completely when the button is hidden */}\n {!noNewButton && (\n <div className=\"auto-crud-toolbar\">\n <Button theme=\"primary\" onClick={() => setItem(emptyItem)}>\n + New\n </Button>\n </div>\n )}\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 // If the \"New\" button is visible, the form is always shown.\n // Otherwise, the form is only shown when an item is being edited.\n return (\n <div className={`auto-crud ${className ?? ''}`} id={id} style={style}>\n {noNewButton && (!item || item === emptyItem) ? (\n mainSection\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"]}
package/autocrud.obj.js CHANGED
@@ -1 +1 @@
1
- const css = new CSSStyleSheet();css.replaceSync(`.auto-crud{border:1px solid var(--lumo-contrast-20pct);display:flex;overflow:hidden}.auto-crud vaadin-split-layout{flex:1 1 100%}.auto-crud vaadin-split-layout::part(splitter){border-left:1px solid var(--lumo-contrast-20pct);border-top:1px solid var(--lumo-contrast-20pct)}.auto-crud-main{display:flex;flex:1 1 100%;flex-direction:column;min-width:200px}.auto-crud-main vaadin-grid{border:none}.auto-crud-toolbar{align-items:baseline;background-color:var(--lumo-contrast-5pct);border-top:1px solid var(--lumo-contrast-10pct);display:flex;flex-shrink:0;justify-content:flex-end;padding:var(--lumo-space-s) var(--lumo-space-m)}.auto-crud-form{align-items:stretch;display:flex;flex-direction:column;min-width:300px;width:40%}.auto-crud .auto-crud-form:before{box-shadow:var(--lumo-box-shadow-s);content:"";height:100%;pointer-events:none;position:absolute;width:100%;z-index:1}.auto-crud-form-header{padding:var(--lumo-space-m) var(--lumo-space-m) var(--lumo-space-s) var(--lumo-space-m)}.auto-crud .auto-form,.auto-crud-dialog .auto-form{align-items:stretch;display:flex;flex:1 1 0;flex-direction:column}.auto-crud .auto-form-fields,.auto-crud-dialog .auto-form-fields{flex:1 1 0;min-height:0;overflow-y:auto;padding:0 var(--lumo-space-m)}.auto-crud .auto-form-toolbar,.auto-crud-dialog .auto-form-toolbar{background-color:var(--lumo-contrast-5pct);border-top:1px solid var(--lumo-contrast-10pct);flex:0 0 auto;padding:var(--lumo-space-s) var(--lumo-space-m)}.auto-crud-dialog{bottom:0;left:0;right:0;top:0}.auto-crud-dialog::part(overlay){border-radius:0;height:100%;width:100%}.auto-crud-dialog::part(content){padding:0}.auto-crud-dialog .auto-crud-dialog-header{align-items:center;display:flex;justify-content:space-between;width:100%}.auto-crud-dialog .auto-form{height:100%;width:100%}`);export default css;
1
+ const css = new CSSStyleSheet();css.replaceSync(`.auto-crud{border:1px solid var(--lumo-contrast-20pct);display:flex;height:462px;overflow:hidden}.auto-crud>vaadin-split-layout{align-items:stretch;flex:1 1 100%}.auto-crud>vaadin-split-layout::part(splitter){border-left:1px solid var(--lumo-contrast-20pct);border-top:1px solid var(--lumo-contrast-20pct)}.auto-crud-main{display:flex;flex:1 1 100%;flex-direction:column;min-width:200px}.auto-crud-main>vaadin-grid{border:none;height:auto}.auto-crud-toolbar{align-items:baseline;background-color:var(--lumo-contrast-5pct);border-top:1px solid var(--lumo-contrast-10pct);display:flex;flex-shrink:0;justify-content:flex-end;padding:var(--lumo-space-s) var(--lumo-space-m)}.auto-crud-form{align-items:stretch;display:flex;flex-direction:column;min-width:300px;width:40%}.auto-crud .auto-crud-form:before{box-shadow:var(--lumo-box-shadow-s);content:"";height:100%;pointer-events:none;position:absolute;width:100%;z-index:1}.auto-crud-form-header{padding:var(--lumo-space-m) var(--lumo-space-m) var(--lumo-space-s) var(--lumo-space-m)}.auto-crud .auto-form,.auto-crud-dialog .auto-form{align-items:stretch;display:flex;flex:1 1 0;flex-direction:column}.auto-crud .auto-form-fields,.auto-crud-dialog .auto-form-fields{flex:1 1 0;min-height:0;overflow-y:auto;padding:0 var(--lumo-space-m)}.auto-crud .auto-form-toolbar,.auto-crud-dialog .auto-form-toolbar{background-color:var(--lumo-contrast-5pct);border-top:1px solid var(--lumo-contrast-10pct);flex:0 0 auto;padding:var(--lumo-space-s) var(--lumo-space-m)}.auto-crud-dialog{bottom:0;left:0;right:0;top:0}.auto-crud-dialog::part(overlay){border-radius:0;height:100%;width:100%}.auto-crud-dialog::part(content){padding:0}.auto-crud-dialog .auto-crud-dialog-header{align-items:center;display:flex;justify-content:space-between;width:100%}.auto-crud-dialog .auto-form{height:100%;width:100%}`);export default css;
@@ -22,7 +22,7 @@ export function AutoGridDecimalRenderer({ item }) {
22
22
  }
23
23
  export function AutoGridEnumRenderer({ item }) {
24
24
  const context = useContext(ColumnContext);
25
- const value = getColumnValue(context, item) || '';
25
+ const value = getColumnValue(context, item) ?? '';
26
26
  return _jsx("span", { children: convertToTitleCase(value) });
27
27
  }
28
28
  export function AutoGridBooleanRenderer({ item }) {
@@ -1 +1 @@
1
- {"version":3,"file":"autogrid-renderers.js","sourceRoot":"","sources":["src/autogrid-renderers.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { GridItemModel } from '@vaadin/react-components/Grid.js';\nimport type { GridColumnElement } from '@vaadin/react-components/GridColumn.js';\nimport { Icon } from '@vaadin/react-components/Icon.js';\nimport { type ComponentType, createContext, type CSSProperties, type JSX, useContext } from 'react';\nimport { ColumnContext } from './autogrid-column-context';\nimport type { ItemCounts } from './data-provider';\nimport { useLocaleFormatter } from './locale.js';\nimport { convertToTitleCase } from './util';\n\n// eslint-disable-next-line\nimport '@vaadin/vaadin-lumo-styles/vaadin-iconset.js';\n\nexport type RendererOptions<TItem> = {\n item: TItem;\n model: GridItemModel<TItem>;\n original: GridColumnElement<TItem>;\n};\n\nfunction getColumnValue<TItem>(context: ColumnContext, item: TItem): any {\n const path = context.propertyInfo.name;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n return path.split('.').reduce<any>((obj, property) => (obj ? obj[property] : undefined), item);\n}\n\nconst fontVariantStyle: CSSProperties = { fontVariantNumeric: 'tabular-nums' };\n\nexport function AutoGridIntegerRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const formatter = useLocaleFormatter();\n const context = useContext(ColumnContext)!;\n return <span style={fontVariantStyle}>{formatter.formatInteger(getColumnValue(context, item))}</span>;\n}\n\nexport function AutoGridDecimalRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const formatter = useLocaleFormatter();\n const context = useContext(ColumnContext)!;\n return <span style={fontVariantStyle}>{formatter.formatDecimal(getColumnValue(context, item))}</span>;\n}\n\nexport function AutoGridEnumRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const context = useContext(ColumnContext)!;\n const value = getColumnValue(context, item) || '';\n return <span>{convertToTitleCase(value)}</span>;\n}\n\nexport function AutoGridBooleanRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const context = useContext(ColumnContext)!;\n const value = getColumnValue(context, item);\n if (value) {\n return <Icon aria-label=\"false\" icon=\"lumo:checkmark\" />;\n }\n return <Icon aria-label=\"true\" style={{ color: 'var(--lumo-secondary-text-color)' }} icon=\"lumo:minus\" />;\n}\n\nexport function AutoGridDateRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const formatter = useLocaleFormatter();\n const context = useContext(ColumnContext)!;\n return <span style={fontVariantStyle}>{formatter.formatDate(getColumnValue(context, item))}</span>;\n}\n\nexport function AutoGridTimeRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const formatter = useLocaleFormatter();\n const context = useContext(ColumnContext)!;\n return <span style={fontVariantStyle}>{formatter.formatLocalTime(getColumnValue(context, item))}</span>;\n}\n\nexport function AutoGridDateTimeRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const formatter = useLocaleFormatter();\n const context = useContext(ColumnContext)!;\n return <span style={fontVariantStyle}>{formatter.formatLocalDateTime(getColumnValue(context, item))}</span>;\n}\n\nexport function AutoGridJsonRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const context = useContext(ColumnContext)!;\n const value = getColumnValue(context, item);\n const jsonString = value ? JSON.stringify(value) : '';\n const jsonPreview = jsonString.length > 50 ? `${jsonString.substring(0, 50)}...` : jsonString;\n return <span>{jsonPreview}</span>;\n}\n\nexport function AutoGridRowNumberRenderer<TItem>({ model }: RendererOptions<TItem>): JSX.Element {\n return <>{model.index + 1}</>;\n}\n\nexport type FooterContextType = {\n totalCount?: boolean;\n filteredCount?: boolean;\n footerCountRenderer?: ComponentType<ItemCounts>;\n itemCounts?: ItemCounts;\n};\n\nexport const FooterContext = createContext<FooterContextType>(undefined!);\n\nexport function AutoGridFooterItemCountRenderer(): JSX.Element {\n const footerContext = useContext(FooterContext);\n const { totalCount, filteredCount, itemCounts, footerCountRenderer: FooterRenderer } = footerContext;\n\n if (FooterRenderer) {\n return <FooterRenderer {...itemCounts} />;\n }\n\n let filterCountText: string | undefined;\n if (filteredCount && itemCounts?.filteredCount !== undefined) {\n filterCountText =\n totalCount && itemCounts.totalCount !== undefined\n ? `Showing: ${itemCounts.filteredCount} out of ${itemCounts.totalCount}`\n : `Showing: ${itemCounts.filteredCount}`;\n } else if (totalCount && itemCounts?.totalCount !== undefined) {\n filterCountText = `Total: ${itemCounts.totalCount}`;\n }\n if (filterCountText) {\n return <p>{filterCountText}</p>;\n }\n return <></>;\n}\n"]}
1
+ {"version":3,"file":"autogrid-renderers.js","sourceRoot":"","sources":["src/autogrid-renderers.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { GridItemModel } from '@vaadin/react-components/Grid.js';\nimport type { GridColumnElement } from '@vaadin/react-components/GridColumn.js';\nimport { Icon } from '@vaadin/react-components/Icon.js';\nimport { type ComponentType, createContext, type CSSProperties, type JSX, useContext } from 'react';\nimport { ColumnContext } from './autogrid-column-context';\nimport type { ItemCounts } from './data-provider';\nimport { useLocaleFormatter } from './locale.js';\nimport { convertToTitleCase } from './util';\n\n// eslint-disable-next-line\nimport '@vaadin/vaadin-lumo-styles/vaadin-iconset.js';\n\nexport type RendererOptions<TItem> = {\n item: TItem;\n model: GridItemModel<TItem>;\n original: GridColumnElement<TItem>;\n};\n\nfunction getColumnValue<TItem>(context: ColumnContext, item: TItem): any {\n const path = context.propertyInfo.name;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n return path.split('.').reduce<any>((obj, property) => (obj ? obj[property] : undefined), item);\n}\n\nconst fontVariantStyle: CSSProperties = { fontVariantNumeric: 'tabular-nums' };\n\nexport function AutoGridIntegerRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const formatter = useLocaleFormatter();\n const context = useContext(ColumnContext)!;\n return <span style={fontVariantStyle}>{formatter.formatInteger(getColumnValue(context, item))}</span>;\n}\n\nexport function AutoGridDecimalRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const formatter = useLocaleFormatter();\n const context = useContext(ColumnContext)!;\n return <span style={fontVariantStyle}>{formatter.formatDecimal(getColumnValue(context, item))}</span>;\n}\n\nexport function AutoGridEnumRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const context = useContext(ColumnContext)!;\n const value = getColumnValue(context, item) ?? '';\n return <span>{convertToTitleCase(value)}</span>;\n}\n\nexport function AutoGridBooleanRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const context = useContext(ColumnContext)!;\n const value = getColumnValue(context, item);\n if (value) {\n return <Icon aria-label=\"false\" icon=\"lumo:checkmark\" />;\n }\n return <Icon aria-label=\"true\" style={{ color: 'var(--lumo-secondary-text-color)' }} icon=\"lumo:minus\" />;\n}\n\nexport function AutoGridDateRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const formatter = useLocaleFormatter();\n const context = useContext(ColumnContext)!;\n return <span style={fontVariantStyle}>{formatter.formatDate(getColumnValue(context, item))}</span>;\n}\n\nexport function AutoGridTimeRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const formatter = useLocaleFormatter();\n const context = useContext(ColumnContext)!;\n return <span style={fontVariantStyle}>{formatter.formatLocalTime(getColumnValue(context, item))}</span>;\n}\n\nexport function AutoGridDateTimeRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const formatter = useLocaleFormatter();\n const context = useContext(ColumnContext)!;\n return <span style={fontVariantStyle}>{formatter.formatLocalDateTime(getColumnValue(context, item))}</span>;\n}\n\nexport function AutoGridJsonRenderer<TItem>({ item }: RendererOptions<TItem>): JSX.Element {\n const context = useContext(ColumnContext)!;\n const value = getColumnValue(context, item);\n const jsonString = value ? JSON.stringify(value) : '';\n const jsonPreview = jsonString.length > 50 ? `${jsonString.substring(0, 50)}...` : jsonString;\n return <span>{jsonPreview}</span>;\n}\n\nexport function AutoGridRowNumberRenderer<TItem>({ model }: RendererOptions<TItem>): JSX.Element {\n return <>{model.index + 1}</>;\n}\n\nexport type FooterContextType = {\n totalCount?: boolean;\n filteredCount?: boolean;\n footerCountRenderer?: ComponentType<ItemCounts>;\n itemCounts?: ItemCounts;\n};\n\nexport const FooterContext = createContext<FooterContextType>(undefined!);\n\nexport function AutoGridFooterItemCountRenderer(): JSX.Element {\n const footerContext = useContext(FooterContext);\n const { totalCount, filteredCount, itemCounts, footerCountRenderer: FooterRenderer } = footerContext;\n\n if (FooterRenderer) {\n return <FooterRenderer {...itemCounts} />;\n }\n\n let filterCountText: string | undefined;\n if (filteredCount && itemCounts?.filteredCount !== undefined) {\n filterCountText =\n totalCount && itemCounts.totalCount !== undefined\n ? `Showing: ${itemCounts.filteredCount} out of ${itemCounts.totalCount}`\n : `Showing: ${itemCounts.filteredCount}`;\n } else if (totalCount && itemCounts?.totalCount !== undefined) {\n filterCountText = `Total: ${itemCounts.totalCount}`;\n }\n if (filterCountText) {\n return <p>{filterCountText}</p>;\n }\n return <></>;\n}\n"]}
package/index.js CHANGED
@@ -6,7 +6,7 @@ export { useDataProvider, useGridDataProvider, useComboBoxDataProvider } from '.
6
6
  vaadinObj.registrations ??= [];
7
7
  vaadinObj.registrations.push({
8
8
  is: feature ? `@vaadin/hilla-react-crud/${feature}` : '@vaadin/hilla-react-crud',
9
- version: '24.8.0-alpha1',
9
+ version: '24.8.0-alpha3',
10
10
  });
11
11
  })();
12
12
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AAEtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAInG,CAAC,CAAC,OAAO,EAAE,SAAS,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC,EAAE,EAAE;IAC/C,SAAS,CAAC,aAAa,KAAK,EAAE,CAAC;IAC/B,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC;QAC3B,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,4BAA4B,OAAO,EAAE,CAAC,CAAC,CAAC,0BAA0B;QAChF,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;AACL,CAAC,CAAC,EAAE,CAAC","sourcesContent":["export * from './autogrid-feature.js';\nexport type * from './crud.js';\nexport * from './autoform-feature.js';\nexport * from './autocrud-feature.js';\nexport { useDataProvider, useGridDataProvider, useComboBoxDataProvider } from './data-provider.js';\n\n// @ts-expect-error: esbuild injection\n// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n((feature, vaadinObj = (window.Vaadin ??= {})) => {\n vaadinObj.registrations ??= [];\n vaadinObj.registrations.push({\n is: feature ? `@vaadin/hilla-react-crud/${feature}` : '@vaadin/hilla-react-crud',\n version: '24.8.0-alpha1',\n });\n})();\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AAEtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAInG,CAAC,CAAC,OAAO,EAAE,SAAS,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC,EAAE,EAAE;IAC/C,SAAS,CAAC,aAAa,KAAK,EAAE,CAAC;IAC/B,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC;QAC3B,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,4BAA4B,OAAO,EAAE,CAAC,CAAC,CAAC,0BAA0B;QAChF,OAAO,EAAE,eAAe;KACzB,CAAC,CAAC;AACL,CAAC,CAAC,EAAE,CAAC","sourcesContent":["export * from './autogrid-feature.js';\nexport type * from './crud.js';\nexport * from './autoform-feature.js';\nexport * from './autocrud-feature.js';\nexport { useDataProvider, useGridDataProvider, useComboBoxDataProvider } from './data-provider.js';\n\n// @ts-expect-error: esbuild injection\n// eslint-disable-next-line @typescript-eslint/no-unsafe-call\n((feature, vaadinObj = (window.Vaadin ??= {})) => {\n vaadinObj.registrations ??= [];\n vaadinObj.registrations.push({\n is: feature ? `@vaadin/hilla-react-crud/${feature}` : '@vaadin/hilla-react-crud',\n version: '24.8.0-alpha3',\n });\n})();\n"]}
package/locale.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { type DatePickerDate, type DatePickerI18n } from '@vaadin/react-components/DatePicker.js';
2
2
  import { type DateTimePickerI18n } from '@vaadin/react-components/DateTimePicker.js';
3
+ import type { SetRequired } from 'type-fest';
3
4
  export declare const LocaleContext: import("react").Context<string>;
4
5
  export declare class LocaleFormatter {
5
6
  #private;
@@ -13,5 +14,5 @@ export declare class LocaleFormatter {
13
14
  parse(dateString: string): DatePickerDate | undefined;
14
15
  }
15
16
  export declare function useLocaleFormatter(): LocaleFormatter;
16
- export declare function useDatePickerI18n(): DatePickerI18n;
17
+ export declare function useDatePickerI18n(): SetRequired<DatePickerI18n, 'formatDate' | 'parseDate'>;
17
18
  export declare function useDateTimePickerI18n(): DateTimePickerI18n;
package/locale.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"locale.js","sourceRoot":"","sources":["src/locale.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA4C,MAAM,wCAAwC,CAAC;AACrH,OAAO,EAAE,qBAAqB,EAA2B,MAAM,4CAA4C,CAAC;AAC5G,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAE3D,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE/D,SAAS,cAAc,CAAC,MAA2B;IACjD,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG,eAAe;SAC5B,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC;SAChC,OAAO,CAAC,IAAI,EAAE,gBAAgB,CAAC;SAC/B,OAAO,CAAC,GAAG,EAAE,gBAAgB,CAAC;SAC9B,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC;SAC7B,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAEhC,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,aAAa,CAAC,SAA8B,EAAE,KAAc;IACnE,IAAI,CAAC;QACH,OAAO,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,OAAO,eAAe;IACjB,KAAK,CAAsB;IAC3B,UAAU,CAAsB;IAChC,cAAc,CAAsB;IACpC,QAAQ,CAAoB;IAC5B,QAAQ,CAAoB;IAC5B,aAAa,CAAS;IAE/B,YAAY,MAAe;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAE7C,IAAI,CAAC,UAAU,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE;YAChD,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE;YACpD,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,SAAS;YAChB,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,SAAS;SAClB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;YAC5C,qBAAqB,EAAE,CAAC;SACzB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE;YAC5C,qBAAqB,EAAE,CAAC;YACxB,qBAAqB,EAAE,CAAC;SACzB,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC;IAID,UAAU,CAAC,KAA+B;QACxC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;YACnC,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QAED,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,eAAe,CAAC,KAAc;QAC5B,OAAO,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,mBAAmB,CAAC,KAAc;QAChC,OAAO,aAAa,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;IAED,aAAa,CAAC,KAAc;QAC1B,OAAO,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,CAAC;IAED,aAAa,CAAC,KAAc;QAC1B,OAAO,KAAK,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,UAAkB;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QAGvC,MAAM,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC;QAChC,YAAY,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAE3C,IAAI,YAAY,CAAC,WAAW,EAAE,KAAK,IAAI,IAAI,YAAY,CAAC,QAAQ,EAAE,KAAK,KAAK,IAAI,YAAY,CAAC,OAAO,EAAE,KAAK,GAAG,EAAE,CAAC;YAC/G,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IACzC,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,qBAAqB,GAAG,IAAI,iBAAiB,EAAE,CAAC,IAAI,CAAC;AAE3D,MAAM,UAAU,iBAAiB;IAC/B,MAAM,SAAS,GAAG,kBAAkB,EAAE,CAAC;IAEvC,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,CAAC;QACL,GAAG,qBAAqB;QACxB,UAAU,CAAC,KAAK;YACd,OAAO,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;QACD,SAAS,CAAC,KAAK;YACb,OAAO,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;KACF,CAAC,EACF,CAAC,SAAS,CAAC,CACZ,CAAC;AACJ,CAAC;AAED,MAAM,yBAAyB,GAAG,IAAI,qBAAqB,EAAE,CAAC,IAAI,CAAC;AAEnE,MAAM,UAAU,qBAAqB;IACnC,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;IAE3C,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,CAAC;QACL,GAAG,yBAAyB;QAC5B,GAAG,cAAc;KAClB,CAAC,EACF,CAAC,cAAc,CAAC,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { DatePickerElement, type DatePickerDate, type DatePickerI18n } from '@vaadin/react-components/DatePicker.js';\nimport { DateTimePickerElement, type DateTimePickerI18n } from '@vaadin/react-components/DateTimePicker.js';\nimport { createContext, useContext, useMemo } from 'react';\n\nexport const LocaleContext = createContext(navigator.language);\n\nfunction getFormatRegex(format: Intl.DateTimeFormat) {\n const sampleDate = new Date(1234, 5 - 1, 6);\n const formattedSample = format.format(sampleDate);\n const pattern = formattedSample\n .replace('1234', '(?<year>\\\\d+)')\n .replace('05', '(?<month>\\\\d+)')\n .replace('5', '(?<month>\\\\d+)')\n .replace('06', '(?<day>\\\\d+)')\n .replace('6', '(?<day>\\\\d+)');\n\n return new RegExp(pattern, 'u');\n}\n\nfunction tryFormatDate(formatter: Intl.DateTimeFormat, value?: string): string {\n try {\n return value ? formatter.format(new Date(value)) : '';\n } catch {\n return '';\n }\n}\n\nexport class LocaleFormatter {\n readonly #date: Intl.DateTimeFormat;\n readonly #localTime: Intl.DateTimeFormat;\n readonly #localDateTime: Intl.DateTimeFormat;\n readonly #integer: Intl.NumberFormat;\n readonly #decimal: Intl.NumberFormat;\n readonly #parsePattern: RegExp;\n\n constructor(locale?: string) {\n this.#date = new Intl.DateTimeFormat(locale);\n\n this.#localTime = new Intl.DateTimeFormat(locale, {\n hour: 'numeric',\n minute: 'numeric',\n });\n\n this.#localDateTime = new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'numeric',\n year: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n });\n\n this.#integer = new Intl.NumberFormat(locale, {\n maximumFractionDigits: 0,\n });\n\n this.#decimal = new Intl.NumberFormat(locale, {\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n });\n\n this.#parsePattern = getFormatRegex(this.#date);\n }\n\n formatDate(value?: string): string;\n formatDate(value: DatePickerDate): string;\n formatDate(value?: DatePickerDate | string): string {\n if (typeof value === 'object') {\n const { year, month, day } = value;\n const date = new Date();\n date.setFullYear(year, month, day);\n return this.#date.format(date);\n }\n\n return tryFormatDate(this.#date, value);\n }\n\n formatLocalTime(value?: string): string {\n return tryFormatDate(this.#localTime, `2000-01-01T${value}`);\n }\n\n formatLocalDateTime(value?: string): string {\n return tryFormatDate(this.#localDateTime, value);\n }\n\n formatInteger(value?: number): string {\n return value && Number.isFinite(value) ? this.#integer.format(value) : '';\n }\n\n formatDecimal(value?: number): string {\n return value && Number.isFinite(value) ? this.#decimal.format(value) : '';\n }\n\n parse(dateString: string): DatePickerDate | undefined {\n const match = this.#parsePattern.exec(dateString);\n const year = Number(match?.groups?.year);\n const month = Number(match?.groups?.month) - 1;\n const day = Number(match?.groups?.day);\n\n // Verify that the parsed date is valid\n const dateInstance = new Date();\n dateInstance.setFullYear(year, month, day);\n\n if (dateInstance.getFullYear() !== year || dateInstance.getMonth() !== month || dateInstance.getDate() !== day) {\n return undefined;\n }\n\n return { year, month, day };\n }\n}\n\nexport function useLocaleFormatter(): LocaleFormatter {\n const locale = useContext(LocaleContext);\n return useMemo(() => new LocaleFormatter(locale), [locale]);\n}\n\nconst defaultDatePickerI18n = new DatePickerElement().i18n;\n\nexport function useDatePickerI18n(): DatePickerI18n {\n const formatter = useLocaleFormatter();\n\n return useMemo(\n () => ({\n ...defaultDatePickerI18n,\n formatDate(value) {\n return formatter.formatDate(value);\n },\n parseDate(value) {\n return formatter.parse(value);\n },\n }),\n [formatter],\n );\n}\n\nconst defaultDateTimePickerI18n = new DateTimePickerElement().i18n;\n\nexport function useDateTimePickerI18n(): DateTimePickerI18n {\n const datePickerI18n = useDatePickerI18n();\n\n return useMemo(\n () => ({\n ...defaultDateTimePickerI18n,\n ...datePickerI18n,\n }),\n [datePickerI18n],\n );\n}\n"]}
1
+ {"version":3,"file":"locale.js","sourceRoot":"","sources":["src/locale.ts"],"names":[],"mappings":"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","sourcesContent":["import { DatePickerElement, type DatePickerDate, type DatePickerI18n } from '@vaadin/react-components/DatePicker.js';\nimport { DateTimePickerElement, type DateTimePickerI18n } from '@vaadin/react-components/DateTimePicker.js';\nimport { createContext, useContext, useMemo } from 'react';\nimport type { SetRequired } from 'type-fest';\n\nexport const LocaleContext = createContext(navigator.language);\n\nfunction getFormatRegex(format: Intl.DateTimeFormat) {\n const sampleDate = new Date(1234, 5 - 1, 6);\n const formattedSample = format.format(sampleDate);\n const pattern = formattedSample\n .replace('1234', '(?<year>\\\\d+)')\n .replace('05', '(?<month>\\\\d+)')\n .replace('5', '(?<month>\\\\d+)')\n .replace('06', '(?<day>\\\\d+)')\n .replace('6', '(?<day>\\\\d+)');\n\n return new RegExp(pattern, 'u');\n}\n\nfunction tryFormatDate(formatter: Intl.DateTimeFormat, value?: string): string {\n try {\n return value ? formatter.format(new Date(value)) : '';\n } catch {\n return '';\n }\n}\n\nexport class LocaleFormatter {\n readonly #date: Intl.DateTimeFormat;\n readonly #localTime: Intl.DateTimeFormat;\n readonly #localDateTime: Intl.DateTimeFormat;\n readonly #integer: Intl.NumberFormat;\n readonly #decimal: Intl.NumberFormat;\n readonly #parsePattern: RegExp;\n\n constructor(locale?: string) {\n this.#date = new Intl.DateTimeFormat(locale);\n\n this.#localTime = new Intl.DateTimeFormat(locale, {\n hour: 'numeric',\n minute: 'numeric',\n });\n\n this.#localDateTime = new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'numeric',\n year: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n });\n\n this.#integer = new Intl.NumberFormat(locale, {\n maximumFractionDigits: 0,\n });\n\n this.#decimal = new Intl.NumberFormat(locale, {\n maximumFractionDigits: 2,\n minimumFractionDigits: 2,\n });\n\n this.#parsePattern = getFormatRegex(this.#date);\n }\n\n formatDate(value?: string): string;\n formatDate(value: DatePickerDate): string;\n formatDate(value?: DatePickerDate | string): string {\n if (typeof value === 'object') {\n const { year, month, day } = value;\n const date = new Date();\n date.setFullYear(year, month, day);\n return this.#date.format(date);\n }\n\n return tryFormatDate(this.#date, value);\n }\n\n formatLocalTime(value?: string): string {\n return tryFormatDate(this.#localTime, `2000-01-01T${value}`);\n }\n\n formatLocalDateTime(value?: string): string {\n return tryFormatDate(this.#localDateTime, value);\n }\n\n formatInteger(value?: number): string {\n return value && Number.isFinite(value) ? this.#integer.format(value) : '';\n }\n\n formatDecimal(value?: number): string {\n return value && Number.isFinite(value) ? this.#decimal.format(value) : '';\n }\n\n parse(dateString: string): DatePickerDate | undefined {\n const match = this.#parsePattern.exec(dateString);\n const year = Number(match?.groups?.year);\n const month = Number(match?.groups?.month) - 1;\n const day = Number(match?.groups?.day);\n\n // Verify that the parsed date is valid\n const dateInstance = new Date();\n dateInstance.setFullYear(year, month, day);\n\n if (dateInstance.getFullYear() !== year || dateInstance.getMonth() !== month || dateInstance.getDate() !== day) {\n return undefined;\n }\n\n return { year, month, day };\n }\n}\n\nexport function useLocaleFormatter(): LocaleFormatter {\n const locale = useContext(LocaleContext);\n return useMemo(() => new LocaleFormatter(locale), [locale]);\n}\n\nconst defaultDatePickerI18n = new DatePickerElement().i18n;\n\nexport function useDatePickerI18n(): SetRequired<DatePickerI18n, 'formatDate' | 'parseDate'> {\n const formatter = useLocaleFormatter();\n\n return useMemo(\n () => ({\n ...defaultDatePickerI18n,\n formatDate(value) {\n return formatter.formatDate(value);\n },\n parseDate(value) {\n return formatter.parse(value);\n },\n }),\n [formatter],\n );\n}\n\nconst defaultDateTimePickerI18n = new DateTimePickerElement().i18n;\n\nexport function useDateTimePickerI18n(): DateTimePickerI18n {\n const datePickerI18n = useDatePickerI18n();\n\n return useMemo(\n () => ({\n ...defaultDateTimePickerI18n,\n ...datePickerI18n,\n }),\n [datePickerI18n],\n );\n}\n"]}
package/model-info.js CHANGED
@@ -75,9 +75,7 @@ export class ModelInfo {
75
75
  }
76
76
  const rootProperties = modelInfo.getRootProperties();
77
77
  let idProperty = rootProperties.find((propertyInfo) => hasAnnotation(propertyInfo.meta, 'jakarta.persistence.Id'));
78
- if (!idProperty) {
79
- idProperty = rootProperties.find((propertyInfo) => propertyInfo.name === 'id');
80
- }
78
+ idProperty ??= rootProperties.find((propertyInfo) => propertyInfo.name === 'id');
81
79
  return idProperty;
82
80
  }
83
81
  static resolvePropertyModel(modelInstance, path) {
package/model-info.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"model-info.js","sourceRoot":"","sources":["src/model-info.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BooleanModel,\n NumberModel,\n StringModel,\n _meta,\n createDetachedModel,\n type AbstractModel,\n type DetachedModelConstructor,\n type ModelMetadata,\n EnumModel,\n ObjectModel,\n} from '@vaadin/hilla-lit-form';\n\nexport type PropertyType =\n | 'boolean'\n | 'date'\n | 'datetime'\n | 'decimal'\n | 'enum'\n | 'integer'\n | 'object'\n | 'string'\n | 'time'\n | undefined;\n\nconst javaTypeMap: Record<string, PropertyType> = {\n byte: 'integer',\n 'java.lang.Byte': 'integer',\n short: 'integer',\n 'java.lang.Short': 'integer',\n int: 'integer',\n 'java.lang.Integer': 'integer',\n long: 'integer',\n 'java.lang.Long': 'integer',\n float: 'decimal',\n 'java.lang.Float': 'decimal',\n double: 'decimal',\n 'java.lang.Double': 'decimal',\n 'java.time.LocalDate': 'date',\n 'java.time.LocalTime': 'time',\n 'java.time.OffsetTime': 'time',\n 'java.time.LocalDateTime': 'datetime',\n 'java.time.OffsetDateTime': 'datetime',\n 'java.time.ZonedDateTime': 'datetime',\n 'java.util.Date': 'datetime',\n 'java.sql.Date': 'datetime',\n};\n\nfunction determinePropertyType(model: AbstractModel): PropertyType {\n // Try detecting by Java type\n const { javaType } = model[_meta];\n const propertyType = javaType ? javaTypeMap[javaType] : undefined;\n if (propertyType) {\n return propertyType;\n }\n\n // Otherwise detect by model instance\n if (model instanceof StringModel) {\n return 'string';\n } else if (model instanceof NumberModel) {\n return 'decimal';\n } else if (model instanceof BooleanModel) {\n return 'boolean';\n } else if (model instanceof EnumModel) {\n return 'enum';\n } else if (model instanceof ObjectModel) {\n return 'object';\n }\n\n return undefined;\n}\n\nexport interface PropertyInfo {\n name: string;\n humanReadableName: string;\n type: PropertyType;\n meta: ModelMetadata;\n model: AbstractModel;\n}\n\nexport function hasAnnotation(meta: ModelMetadata, annotationName: string): boolean {\n return meta.annotations?.some((annotation) => annotation.name === annotationName) ?? false;\n}\n\n// This is from vaadin-grid-column.js, should be used from there maybe. At least we must be 100% sure to match grid and fields\nexport function _generateHeader(path: string): string {\n return path\n .substring(path.lastIndexOf('.') + 1)\n .replace(/([A-Z])/gu, '-$1')\n .toLowerCase()\n .replace(/-/gu, ' ')\n .replace(/^./u, (match) => match.toUpperCase());\n}\n\nconst getPropertyNames = (model: DetachedModelConstructor<AbstractModel>): string[] => {\n const propertyNames: string[] = [];\n\n for (let proto = model; proto !== ObjectModel; proto = Object.getPrototypeOf(proto)) {\n // parent properties are added at the beginning\n propertyNames.unshift(...Object.keys(Object.getOwnPropertyDescriptors(proto.prototype)).filter((p) => p !== 'new'));\n }\n\n return propertyNames;\n};\n\nexport class ModelInfo {\n private readonly modelInstance: AbstractModel;\n\n readonly idProperty?: PropertyInfo;\n\n constructor(model: DetachedModelConstructor<AbstractModel>, idPropertyName?: string) {\n this.modelInstance = createDetachedModel(model);\n\n // Try to find id property\n this.idProperty = ModelInfo.resolveIdProperty(this, idPropertyName);\n }\n\n private static resolveIdProperty(modelInfo: ModelInfo, idPropertyName?: string): PropertyInfo | undefined {\n // Return explicit property if defined\n if (idPropertyName) {\n return modelInfo.getProperty(idPropertyName);\n }\n\n // Otherwise check defaults\n const rootProperties = modelInfo.getRootProperties();\n // Check for @Id annotation\n let idProperty = rootProperties.find((propertyInfo) => hasAnnotation(propertyInfo.meta, 'jakarta.persistence.Id'));\n // Check for id name as fallback\n if (!idProperty) {\n idProperty = rootProperties.find((propertyInfo) => propertyInfo.name === 'id');\n }\n\n return idProperty;\n }\n\n private static resolvePropertyModel(modelInstance: AbstractModel, path: string): AbstractModel | undefined {\n const parts = path.split('.');\n let currentModel: AbstractModel | undefined = modelInstance;\n for (const part of parts) {\n if (!currentModel || !(currentModel instanceof ObjectModel)) {\n return undefined;\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n currentModel = (currentModel as any)[part];\n }\n return currentModel;\n }\n\n getRootProperties(path?: string): PropertyInfo[] {\n const model = path ? ModelInfo.resolvePropertyModel(this.modelInstance, path) : this.modelInstance;\n if (!model) {\n return [];\n }\n return getPropertyNames(model.constructor as any)\n .map((name) => {\n const effectivePath = path ? `${path}.${name}` : name;\n return this.getProperty(effectivePath);\n })\n .filter(Boolean) as PropertyInfo[];\n }\n\n getProperty(path: string): PropertyInfo | undefined {\n const propertyModel = ModelInfo.resolvePropertyModel(this.modelInstance, path);\n if (!propertyModel?.[_meta]) {\n return undefined;\n }\n\n const pathParts = path.split('.');\n const name = pathParts[pathParts.length - 1];\n\n const meta = propertyModel[_meta];\n const humanReadableName = _generateHeader(name);\n const type = determinePropertyType(propertyModel);\n\n return {\n name: path,\n humanReadableName,\n type,\n meta,\n model: propertyModel,\n };\n }\n\n getProperties(paths: string[]): PropertyInfo[] {\n return paths.map((path) => this.getProperty(path)).filter(Boolean) as PropertyInfo[];\n }\n}\n\nexport function getDefaultProperties(modelInfo: ModelInfo): PropertyInfo[] {\n // Start from root properties\n const properties = modelInfo.getRootProperties();\n return (\n properties\n // Auto-expand nested properties of one-to-one relations\n .flatMap((prop) => {\n if (hasAnnotation(prop.meta, 'jakarta.persistence.OneToOne')) {\n return modelInfo.getRootProperties(prop.name);\n }\n return prop;\n })\n // Exclude properties that have an unknown type, or are annotated with id\n // and version\n .filter(\n (prop) =>\n !!prop.type &&\n !(\n hasAnnotation(prop.meta, 'jakarta.persistence.Id') ||\n hasAnnotation(prop.meta, 'jakarta.persistence.Version')\n ),\n )\n );\n}\n"]}
1
+ {"version":3,"file":"model-info.js","sourceRoot":"","sources":["src/model-info.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BooleanModel,\n NumberModel,\n StringModel,\n _meta,\n createDetachedModel,\n type AbstractModel,\n type DetachedModelConstructor,\n type ModelMetadata,\n EnumModel,\n ObjectModel,\n} from '@vaadin/hilla-lit-form';\n\nexport type PropertyType =\n | 'boolean'\n | 'date'\n | 'datetime'\n | 'decimal'\n | 'enum'\n | 'integer'\n | 'object'\n | 'string'\n | 'time'\n | undefined;\n\nconst javaTypeMap: Record<string, PropertyType> = {\n byte: 'integer',\n 'java.lang.Byte': 'integer',\n short: 'integer',\n 'java.lang.Short': 'integer',\n int: 'integer',\n 'java.lang.Integer': 'integer',\n long: 'integer',\n 'java.lang.Long': 'integer',\n float: 'decimal',\n 'java.lang.Float': 'decimal',\n double: 'decimal',\n 'java.lang.Double': 'decimal',\n 'java.time.LocalDate': 'date',\n 'java.time.LocalTime': 'time',\n 'java.time.OffsetTime': 'time',\n 'java.time.LocalDateTime': 'datetime',\n 'java.time.OffsetDateTime': 'datetime',\n 'java.time.ZonedDateTime': 'datetime',\n 'java.util.Date': 'datetime',\n 'java.sql.Date': 'datetime',\n};\n\nfunction determinePropertyType(model: AbstractModel): PropertyType {\n // Try detecting by Java type\n const { javaType } = model[_meta];\n const propertyType = javaType ? javaTypeMap[javaType] : undefined;\n if (propertyType) {\n return propertyType;\n }\n\n // Otherwise detect by model instance\n if (model instanceof StringModel) {\n return 'string';\n } else if (model instanceof NumberModel) {\n return 'decimal';\n } else if (model instanceof BooleanModel) {\n return 'boolean';\n } else if (model instanceof EnumModel) {\n return 'enum';\n } else if (model instanceof ObjectModel) {\n return 'object';\n }\n\n return undefined;\n}\n\nexport interface PropertyInfo {\n name: string;\n humanReadableName: string;\n type: PropertyType;\n meta: ModelMetadata;\n model: AbstractModel;\n}\n\nexport function hasAnnotation(meta: ModelMetadata, annotationName: string): boolean {\n return meta.annotations?.some((annotation) => annotation.name === annotationName) ?? false;\n}\n\n// This is from vaadin-grid-column.js, should be used from there maybe. At least we must be 100% sure to match grid and fields\nexport function _generateHeader(path: string): string {\n return path\n .substring(path.lastIndexOf('.') + 1)\n .replace(/([A-Z])/gu, '-$1')\n .toLowerCase()\n .replace(/-/gu, ' ')\n .replace(/^./u, (match) => match.toUpperCase());\n}\n\nconst getPropertyNames = (model: DetachedModelConstructor<AbstractModel>): string[] => {\n const propertyNames: string[] = [];\n\n for (let proto = model; proto !== ObjectModel; proto = Object.getPrototypeOf(proto)) {\n // parent properties are added at the beginning\n propertyNames.unshift(...Object.keys(Object.getOwnPropertyDescriptors(proto.prototype)).filter((p) => p !== 'new'));\n }\n\n return propertyNames;\n};\n\nexport class ModelInfo {\n private readonly modelInstance: AbstractModel;\n\n readonly idProperty?: PropertyInfo;\n\n constructor(model: DetachedModelConstructor<AbstractModel>, idPropertyName?: string) {\n this.modelInstance = createDetachedModel(model);\n\n // Try to find id property\n this.idProperty = ModelInfo.resolveIdProperty(this, idPropertyName);\n }\n\n private static resolveIdProperty(modelInfo: ModelInfo, idPropertyName?: string): PropertyInfo | undefined {\n // Return explicit property if defined\n if (idPropertyName) {\n return modelInfo.getProperty(idPropertyName);\n }\n\n // Otherwise check defaults\n const rootProperties = modelInfo.getRootProperties();\n // Check for @Id annotation\n let idProperty = rootProperties.find((propertyInfo) => hasAnnotation(propertyInfo.meta, 'jakarta.persistence.Id'));\n // Check for id name as fallback\n idProperty ??= rootProperties.find((propertyInfo) => propertyInfo.name === 'id');\n\n return idProperty;\n }\n\n private static resolvePropertyModel(modelInstance: AbstractModel, path: string): AbstractModel | undefined {\n const parts = path.split('.');\n let currentModel: AbstractModel | undefined = modelInstance;\n for (const part of parts) {\n if (!currentModel || !(currentModel instanceof ObjectModel)) {\n return undefined;\n }\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n currentModel = (currentModel as any)[part];\n }\n return currentModel;\n }\n\n getRootProperties(path?: string): PropertyInfo[] {\n const model = path ? ModelInfo.resolvePropertyModel(this.modelInstance, path) : this.modelInstance;\n if (!model) {\n return [];\n }\n return getPropertyNames(model.constructor as any)\n .map((name) => {\n const effectivePath = path ? `${path}.${name}` : name;\n return this.getProperty(effectivePath);\n })\n .filter(Boolean) as PropertyInfo[];\n }\n\n getProperty(path: string): PropertyInfo | undefined {\n const propertyModel = ModelInfo.resolvePropertyModel(this.modelInstance, path);\n if (!propertyModel?.[_meta]) {\n return undefined;\n }\n\n const pathParts = path.split('.');\n const name = pathParts[pathParts.length - 1];\n\n const meta = propertyModel[_meta];\n const humanReadableName = _generateHeader(name);\n const type = determinePropertyType(propertyModel);\n\n return {\n name: path,\n humanReadableName,\n type,\n meta,\n model: propertyModel,\n };\n }\n\n getProperties(paths: string[]): PropertyInfo[] {\n return paths.map((path) => this.getProperty(path)).filter(Boolean) as PropertyInfo[];\n }\n}\n\nexport function getDefaultProperties(modelInfo: ModelInfo): PropertyInfo[] {\n // Start from root properties\n const properties = modelInfo.getRootProperties();\n return (\n properties\n // Auto-expand nested properties of one-to-one relations\n .flatMap((prop) => {\n if (hasAnnotation(prop.meta, 'jakarta.persistence.OneToOne')) {\n return modelInfo.getRootProperties(prop.name);\n }\n return prop;\n })\n // Exclude properties that have an unknown type, or are annotated with id\n // and version\n .filter(\n (prop) =>\n !!prop.type &&\n !(\n hasAnnotation(prop.meta, 'jakarta.persistence.Id') ||\n hasAnnotation(prop.meta, 'jakarta.persistence.Version')\n ),\n )\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/hilla-react-crud",
3
- "version": "24.8.0-alpha1",
3
+ "version": "24.8.0-alpha3",
4
4
  "description": "Hilla CRUD utils for React",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -22,6 +22,7 @@
22
22
  "lint:fix": "eslint src test --fix",
23
23
  "test": "vitest --run",
24
24
  "test:coverage": "vitest --run --coverage",
25
+ "test:react": "npm run test",
25
26
  "test:watch": "vitest",
26
27
  "typecheck": "tsc --noEmit"
27
28
  },
@@ -53,10 +54,11 @@
53
54
  "access": "public"
54
55
  },
55
56
  "dependencies": {
56
- "@vaadin/hilla-frontend": "24.8.0-alpha1",
57
- "@vaadin/hilla-lit-form": "24.8.0-alpha1",
58
- "@vaadin/hilla-react-form": "24.8.0-alpha1",
59
- "@vaadin/react-components": "24.7.0-beta1"
57
+ "@vaadin/hilla-frontend": "24.8.0-alpha3",
58
+ "@vaadin/hilla-lit-form": "24.8.0-alpha3",
59
+ "@vaadin/hilla-react-form": "24.8.0-alpha3",
60
+ "@vaadin/react-components": "24.8.0-alpha8",
61
+ "type-fest": "4.35.0"
60
62
  },
61
63
  "peerDependencies": {
62
64
  "react": "18 || 19",
package/util.js CHANGED
@@ -24,7 +24,7 @@ function useFeatureRegistration(feature) {
24
24
  vaadinObj.registrations ??= [];
25
25
  vaadinObj.registrations.push({
26
26
  is: feature ? `@vaadin/hilla-react-crud/${feature}` : '@vaadin/hilla-react-crud',
27
- version: '24.8.0-alpha1',
27
+ version: '24.8.0-alpha3',
28
28
  });
29
29
  })(feature);
30
30
  }
package/util.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["src/util.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { type CSSProperties, forwardRef } from 'react';\nimport type FilterUnion from './types/com/vaadin/hilla/crud/filter/FilterUnion.js';\n\nexport type ComponentStyleProps = Readonly<{\n id?: string;\n style?: CSSProperties;\n className?: string;\n}>;\n\nexport function convertToTitleCase(inputString: string): string {\n // Convert underscores to spaces\n const stringWithSpaces = inputString.replace(/_/gu, ' ');\n\n // Convert to title case\n const words = stringWithSpaces.split(' ');\n const titleCaseWords = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());\n\n // Join the title case words with spaces\n return titleCaseWords.join(' ');\n}\n\nexport function registerStylesheet(stylesheet: CSSStyleSheet): void {\n const css = Array.from(stylesheet.cssRules)\n .map((rule) => rule.cssText)\n .join('\\n');\n\n const styleTag = document.createElement('style');\n styleTag.textContent = css;\n document.head.prepend(styleTag);\n}\n\nconst registeredFeatures = new Set<string>();\nfunction useFeatureRegistration(feature: string): void {\n if (registeredFeatures.has(feature)) {\n return;\n }\n\n registeredFeatures.add(feature);\n // @ts-expect-error: esbuild injection\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n ((feature, vaadinObj = (window.Vaadin ??= {})) => {\n vaadinObj.registrations ??= [];\n vaadinObj.registrations.push({\n is: feature ? `@vaadin/hilla-react-crud/${feature}` : '@vaadin/hilla-react-crud',\n version: '24.8.0-alpha1',\n });\n})(feature);\n}\n\nexport function featureRegistration<C extends (...args: any[]) => any>(Component: C, feature: string): C {\n return forwardRef<unknown, React.JSX.LibraryManagedAttributes<C, NonNullable<unknown>>>((props, ref) => {\n useFeatureRegistration(feature);\n return <Component {...(props as any)} ref={ref} />;\n }) as unknown as C;\n}\n\nexport function isFilterEmpty(filter: FilterUnion): boolean {\n if (filter['@type'] === 'and' || filter['@type'] === 'or') {\n if (filter.children.length === 0) {\n return true;\n }\n return filter.children.every((child) => isFilterEmpty(child as FilterUnion));\n }\n if ('filterValue' in filter) {\n return filter.filterValue === '';\n }\n throw new Error(`Unknown filter type: ${'@type' in filter ? filter['@type'] : JSON.stringify(filter)} `);\n}\n"]}
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["src/util.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { type CSSProperties, forwardRef } from 'react';\nimport type FilterUnion from './types/com/vaadin/hilla/crud/filter/FilterUnion.js';\n\nexport type ComponentStyleProps = Readonly<{\n id?: string;\n style?: CSSProperties;\n className?: string;\n}>;\n\nexport function convertToTitleCase(inputString: string): string {\n // Convert underscores to spaces\n const stringWithSpaces = inputString.replace(/_/gu, ' ');\n\n // Convert to title case\n const words = stringWithSpaces.split(' ');\n const titleCaseWords = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());\n\n // Join the title case words with spaces\n return titleCaseWords.join(' ');\n}\n\nexport function registerStylesheet(stylesheet: CSSStyleSheet): void {\n const css = Array.from(stylesheet.cssRules)\n .map((rule) => rule.cssText)\n .join('\\n');\n\n const styleTag = document.createElement('style');\n styleTag.textContent = css;\n document.head.prepend(styleTag);\n}\n\nconst registeredFeatures = new Set<string>();\nfunction useFeatureRegistration(feature: string): void {\n if (registeredFeatures.has(feature)) {\n return;\n }\n\n registeredFeatures.add(feature);\n // @ts-expect-error: esbuild injection\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n ((feature, vaadinObj = (window.Vaadin ??= {})) => {\n vaadinObj.registrations ??= [];\n vaadinObj.registrations.push({\n is: feature ? `@vaadin/hilla-react-crud/${feature}` : '@vaadin/hilla-react-crud',\n version: '24.8.0-alpha3',\n });\n})(feature);\n}\n\nexport function featureRegistration<C extends (...args: any[]) => any>(Component: C, feature: string): C {\n return forwardRef<unknown, React.JSX.LibraryManagedAttributes<C, NonNullable<unknown>>>((props, ref) => {\n useFeatureRegistration(feature);\n return <Component {...(props as any)} ref={ref} />;\n }) as unknown as C;\n}\n\nexport function isFilterEmpty(filter: FilterUnion): boolean {\n if (filter['@type'] === 'and' || filter['@type'] === 'or') {\n if (filter.children.length === 0) {\n return true;\n }\n return filter.children.every((child) => isFilterEmpty(child as FilterUnion));\n }\n if ('filterValue' in filter) {\n return filter.filterValue === '';\n }\n throw new Error(`Unknown filter type: ${'@type' in filter ? filter['@type'] : JSON.stringify(filter)} `);\n}\n"]}