@sonic-equipment/ui 0.0.112 → 0.0.113

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.
Files changed (26) hide show
  1. package/dist/index.d.ts +23 -8
  2. package/dist/index.js +23 -10
  3. package/dist/src/cards/orderline-card/connected-orderline-card.d.ts +6 -0
  4. package/dist/src/cards/orderline-card/connected-remove-button.d.ts +5 -0
  5. package/dist/src/cards/orderline-card/orderline-card.d.ts +25 -0
  6. package/dist/src/cards/orderline-card/orderline-card.stories.d.ts +46 -0
  7. package/dist/src/delivery-time/delivery-time.d.ts +5 -0
  8. package/dist/src/delivery-time/delivery-time.stories.d.ts +13 -0
  9. package/dist/src/display/product-price/product-price.d.ts +2 -1
  10. package/dist/src/display/product-price/product-total-price.d.ts +7 -0
  11. package/dist/src/display/product-price/product-total-price.stories.d.ts +14 -0
  12. package/dist/src/intl/translation-id.d.ts +1 -1
  13. package/dist/src/intl/use-format-message.d.ts +11 -5
  14. package/dist/src/lists/orderline-list/orderline-list.d.ts +7 -0
  15. package/dist/src/lists/orderline-list/orderline-list.stories.d.ts +15 -0
  16. package/dist/src/modals/confirmation/confirmation-dialog.d.ts +10 -0
  17. package/dist/src/modals/confirmation/confirmation-dialog.stories.d.ts +19 -0
  18. package/dist/src/modals/dialog/dialog.d.ts +10 -5
  19. package/dist/src/shared/api/bff/hooks/use-fetch-announcements.d.ts +4 -1
  20. package/dist/src/shared/feature-flags/use-feature-flags.d.ts +1 -1
  21. package/dist/src/shared/model/price.d.ts +5 -0
  22. package/dist/src/shared/utils/date.d.ts +11 -0
  23. package/dist/src/shared/utils/date.test.d.ts +1 -0
  24. package/dist/styles.css +5 -3
  25. package/package.json +6 -3
  26. /package/dist/src/shared/{fetch/constants.d.ts → utils/time.d.ts} +0 -0
package/dist/index.d.ts CHANGED
@@ -128,7 +128,7 @@ declare const request: Request;
128
128
 
129
129
  declare const features: {
130
130
  readonly language: "language";
131
- readonly pdpv1: "pdpV1";
131
+ readonly pdp: "pdpV2";
132
132
  readonly plpv1: "plpV1";
133
133
  readonly searchv1: "searchV1";
134
134
  };
@@ -3827,17 +3827,22 @@ type TranslationId$1 =
3827
3827
  | "Unfortnately, We found no articles for your search '{0}'"
3828
3828
  | ' to your account to manage your lists.'
3829
3829
  | 'Add to list'
3830
+ | 'Amount: {0}'
3830
3831
  | 'An unexpected error occured'
3831
3832
  | 'Are you looking for information about our service? Please visit our customer support page'
3833
+ | 'Are you sure you want to remove all items from your cart?'
3834
+ | 'Are you sure you want to remove this item from your cart?'
3832
3835
  | 'Cancel'
3833
3836
  | 'Chosen filters'
3834
3837
  | 'Clear filters'
3835
3838
  | 'Clear'
3839
+ | 'Continue'
3836
3840
  | 'Continue shopping'
3837
3841
  | 'Cost overview'
3838
3842
  | 'Country'
3839
3843
  | 'Create new list'
3840
3844
  | 'create account'
3845
+ | 'Delivery expected in {0} {1}'
3841
3846
  | 'Double check your spelling'
3842
3847
  | 'Downloads'
3843
3848
  | 'Excl. VAT'
@@ -3852,14 +3857,17 @@ type TranslationId$1 =
3852
3857
  | 'List name already exists'
3853
3858
  | 'New list name'
3854
3859
  | 'Order number'
3860
+ | 'pc'
3855
3861
  | 'Please Sign In'
3856
3862
  | 'Popular searches'
3857
3863
  | 'Print'
3858
3864
  | 'Product Features'
3859
3865
  | 'Products'
3866
+ | 'Product'
3860
3867
  | 'Quick access'
3861
3868
  | 'Recent searches'
3862
3869
  | 'Recently viewed'
3870
+ | 'Remove all'
3863
3871
  | 'Searching again using more general terms'
3864
3872
  | 'See all results'
3865
3873
  | 'Select a list'
@@ -3979,7 +3987,7 @@ interface UpdateCartLineParams {
3979
3987
  }
3980
3988
  declare function useUpdateCartLineById(): _tanstack_react_query.UseMutationResult<void, Error, UpdateCartLineParams, unknown>;
3981
3989
 
3982
- type TranslationId = "'{0}' in all products" | "Try 'Search' and try to find the product you're looking for" | "Unfortnately, We found no articles for your search '{0}'" | ' to your account to manage your lists.' | 'Add to list' | 'An unexpected error occured' | 'Are you looking for information about our service? Please visit our customer support page' | 'Cancel' | 'Chosen filters' | 'Clear filters' | 'Clear' | 'Continue shopping' | 'Cost overview' | 'Country' | 'Create new list' | 'create account' | 'Double check your spelling' | 'Downloads' | 'Excl. VAT' | 'Explore by categories' | 'Exploring our products by category' | 'Features' | 'Fulfillment method' | 'Hide filters' | 'Incl. VAT' | 'Includes' | 'Language' | 'List name already exists' | 'New list name' | 'Order number' | 'Please Sign In' | 'Popular searches' | 'Print' | 'Product Features' | 'Products' | 'Quick access' | 'Recent searches' | 'Recently viewed' | 'Searching again using more general terms' | 'See all results' | 'Select a list' | 'Shop more efficiently and quicker with a favorites list' | 'Easily add your favorite products' | 'Your favorites are available on multiple devices' | 'Save' | 'Share your favorite list with others' | 'Shipping and handling' | 'Show all' | 'Show filters' | 'Show less' | 'Show' | 'Sorry, there are no products found' | 'Sorry, we could not find matches for' | 'Sort by' | 'Specifications' | 'Submit' | 'Subtotal' | 'Suggestions' | 'The product has been added to your cart.' | 'The product has been updated in your cart.' | 'The product has been removed from your cart.' | 'Unable to add the product to your cart.' | 'Unable to update the product in your cart.' | 'Unable to remove the product from your cart.' | 'Try another search' | 'Total' | 'Use fewer keywords' | 'VAT' | 'Welcome to Sonic Equipment. Please choose your country and language below.' | 'What are you searching for?' | 'You could try checking the spelling of your search query' | 'You could try exploring our products by category' | 'You could try' | 'You must ' | 'article' | 'articles' | 'facet.categories' | 'facet.height' | 'facet.weight' | 'of' | 'sign in' | 'sort.newest' | 'sort.price_asc' | 'sort.price_desc' | 'sort.relevance' | 'tag.limited' | 'tag.new';
3990
+ type TranslationId = "'{0}' in all products" | "Try 'Search' and try to find the product you're looking for" | "Unfortnately, We found no articles for your search '{0}'" | ' to your account to manage your lists.' | 'Add to list' | 'Amount: {0}' | 'An unexpected error occured' | 'Are you looking for information about our service? Please visit our customer support page' | 'Are you sure you want to remove all items from your cart?' | 'Are you sure you want to remove this item from your cart?' | 'Cancel' | 'Chosen filters' | 'Clear filters' | 'Clear' | 'Continue' | 'Continue shopping' | 'Cost overview' | 'Country' | 'Create new list' | 'create account' | 'Delivery expected in {0} {1}' | 'Double check your spelling' | 'Downloads' | 'Excl. VAT' | 'Explore by categories' | 'Exploring our products by category' | 'Features' | 'Fulfillment method' | 'Hide filters' | 'Incl. VAT' | 'Includes' | 'Language' | 'List name already exists' | 'New list name' | 'Order number' | 'pc' | 'Please Sign In' | 'Popular searches' | 'Print' | 'Product Features' | 'Products' | 'Product' | 'Quick access' | 'Recent searches' | 'Recently viewed' | 'Remove all' | 'Searching again using more general terms' | 'See all results' | 'Select a list' | 'Shop more efficiently and quicker with a favorites list' | 'Easily add your favorite products' | 'Your favorites are available on multiple devices' | 'Save' | 'Share your favorite list with others' | 'Shipping and handling' | 'Show all' | 'Show filters' | 'Show less' | 'Show' | 'Sorry, there are no products found' | 'Sorry, we could not find matches for' | 'Sort by' | 'Specifications' | 'Submit' | 'Subtotal' | 'Suggestions' | 'The product has been added to your cart.' | 'The product has been updated in your cart.' | 'The product has been removed from your cart.' | 'Unable to add the product to your cart.' | 'Unable to update the product in your cart.' | 'Unable to remove the product from your cart.' | 'Try another search' | 'Total' | 'Use fewer keywords' | 'VAT' | 'Welcome to Sonic Equipment. Please choose your country and language below.' | 'What are you searching for?' | 'You could try checking the spelling of your search query' | 'You could try exploring our products by category' | 'You could try' | 'You must ' | 'article' | 'articles' | 'facet.categories' | 'facet.height' | 'facet.weight' | 'of' | 'sign in' | 'sort.newest' | 'sort.price_asc' | 'sort.price_desc' | 'sort.relevance' | 'tag.limited' | 'tag.new';
3983
3991
 
3984
3992
  type Translations = Record<TranslationId, string>;
3985
3993
  type FormatMessageFunction = (id: string, ...replacementValues: readonly string[]) => string | undefined;
@@ -4479,9 +4487,10 @@ declare function CountrySelector({ defaultCountryCode, defaultLanguageCode, onCh
4479
4487
 
4480
4488
  interface ProductPriceProps {
4481
4489
  className?: string;
4482
- isVatIncluded: boolean;
4490
+ isVatIncluded: boolean | null;
4483
4491
  originalPrice: number;
4484
4492
  price: number;
4493
+ pricePerUnit?: number;
4485
4494
  }
4486
4495
  declare function ProductPrice({ className, isVatIncluded, originalPrice, price, }: ProductPriceProps): react_jsx_runtime.JSX.Element | undefined;
4487
4496
 
@@ -4624,11 +4633,17 @@ interface IntlProviderProps {
4624
4633
  }
4625
4634
  declare function IntlProvider({ children, formatMessage, languageCode: _languageCode, }: IntlProviderProps): react_jsx_runtime.JSX.Element;
4626
4635
 
4627
- type FormattedMessageFunction = (id: TranslationId, options?: {
4628
- fallbackValue?: string;
4629
- optional?: boolean;
4630
- replacementValues?: Record<string, string>;
4631
- }) => string;
4636
+ interface FormattedMessageFunction {
4637
+ (id: TranslationId, options?: {
4638
+ fallbackValue?: string;
4639
+ optional?: boolean;
4640
+ replacementValues?: Record<string, string>;
4641
+ }): string;
4642
+ pluralize: {
4643
+ (translationId: string, count: number): string;
4644
+ (translationIdPrefix: string, translationId: string, count: number): string;
4645
+ };
4646
+ }
4632
4647
  declare function useFormattedMessage(): FormattedMessageFunction;
4633
4648
 
4634
4649
  interface ProductOverviewGridProps {
package/dist/index.js CHANGED
@@ -483,7 +483,7 @@ const request = (function createRequestFunction() {
483
483
 
484
484
  const features = {
485
485
  language: 'language',
486
- pdpv1: 'pdpV1',
486
+ pdp: 'pdpV2',
487
487
  plpv1: 'plpV1',
488
488
  searchv1: 'searchV1',
489
489
  };
@@ -1347,9 +1347,9 @@ function Button({ _pseudo = 'none', children, className, color = 'primary', cond
1347
1347
  const onClick = (e) => {
1348
1348
  if (_onClick)
1349
1349
  _onClick(e);
1350
+ e.stopPropagation();
1350
1351
  if (type === 'submit')
1351
1352
  return;
1352
- e.stopPropagation();
1353
1353
  e.preventDefault();
1354
1354
  };
1355
1355
  return (jsxs("button", { className: clsx({ [buttonStyles.condensed]: condensed }, { [buttonStyles.icon]: icon }, buttonStyles.button, buttonStyles[variant], buttonStyles[size], buttonStyles[color], buttonStyles[_pseudo], className), "data-disabled": isDisabled ? true : undefined, disabled: isDisabled, onClick: onClick, type: type, children: [jsx(Fragment, { children: showIconOnLeft && jsx("span", { className: buttonStyles.icon, children: icon }) }), children, withArrow && (jsx(GlyphsArrowBoldCapsRightIcon, { className: buttonStyles['right-arrow-icon'] })), showIconOnRight && jsx("span", { className: buttonStyles.icon, children: icon })] }));
@@ -1671,7 +1671,7 @@ const IntlContext = createContext({
1671
1671
 
1672
1672
  function useFormattedMessage() {
1673
1673
  const { formatMessage } = useContext(IntlContext);
1674
- return (id, { fallbackValue, optional, replacementValues } = {}) => {
1674
+ const formatFunction = (id, { fallbackValue, optional, replacementValues } = {}) => {
1675
1675
  const message = formatMessage(id,
1676
1676
  /* The following code converts replacementValues from an object to an array.
1677
1677
  * This is to keep the external API compatible with react-intls version
@@ -1692,6 +1692,13 @@ function useFormattedMessage() {
1692
1692
  console.warn(`Missing translation with id: ${id}`);
1693
1693
  return message || fallbackValue || id;
1694
1694
  };
1695
+ function pluralize(translationIdOrPrefix, translationIdOrCount, count) {
1696
+ return formatFunction((typeof translationIdOrCount === 'number'
1697
+ ? `${translationIdOrPrefix}.${translationIdOrCount === 1 ? 'singular' : 'plural'}`
1698
+ : `${translationIdOrPrefix}.${translationIdOrCount}.${count === 1 ? 'singular' : 'plural'}`));
1699
+ }
1700
+ formatFunction.pluralize = pluralize;
1701
+ return formatFunction;
1695
1702
  }
1696
1703
 
1697
1704
  const FormattedMessage = ({ fallbackValue, id, optional, replacementValues, }) => useFormattedMessage()(id, { fallbackValue, optional, replacementValues });
@@ -1849,9 +1856,9 @@ const formatPrice = (price) => new Intl.NumberFormat('en-US', {
1849
1856
  minimumFractionDigits: 2,
1850
1857
  }).format(price);
1851
1858
 
1852
- var styles$Y = {"product-price":"product-price-module-oIU1K","original-price":"product-price-module-til0s","is-hidden":"product-price-module-V1NCf","current-price-wrapper":"product-price-module-FfVhl","current-price":"product-price-module-pvy2w","wholes":"product-price-module-GCw07","dot":"product-price-module-N56iV","decimals":"product-price-module-eWOOF","vat":"product-price-module-96DoG"};
1859
+ var styles$Y = {"product-price":"product-price-module-oIU1K","original-price":"product-price-module-til0s","is-hidden":"product-price-module-V1NCf","current-price-wrapper":"product-price-module-FfVhl","current-price":"product-price-module-pvy2w","wholes":"product-price-module-GCw07","dot":"product-price-module-N56iV","decimals":"product-price-module-eWOOF","price-per-unit":"product-price-module-syhum","vat":"product-price-module-96DoG"};
1853
1860
 
1854
- function ProductPrice({ className, isVatIncluded, originalPrice, price, }) {
1861
+ function ProductPrice({ className, isVatIncluded = false, originalPrice, price, }) {
1855
1862
  if (isNaN(price))
1856
1863
  return;
1857
1864
  const originalPriceWithCurrency = formatPrice(!isNaN(originalPrice) ? originalPrice : price);
@@ -1860,7 +1867,7 @@ function ProductPrice({ className, isVatIncluded, originalPrice, price, }) {
1860
1867
  const showOriginalPrice = priceWithCurrency !== originalPriceWithCurrency;
1861
1868
  return (jsxs("div", { className: clsx(className, styles$Y['product-price']), children: [jsx("span", { className: clsx(styles$Y['original-price'], {
1862
1869
  [styles$Y['is-hidden']]: !showOriginalPrice,
1863
- }), children: originalPriceWithCurrency }), jsxs("div", { className: styles$Y['current-price-wrapper'], children: [jsxs("div", { className: styles$Y['current-price'], children: [jsx("span", { className: styles$Y.wholes, children: wholes }), jsx("span", { className: styles$Y.dot, children: "." }), jsx("span", { className: styles$Y.decimals, children: decimals })] }), jsx("span", { className: styles$Y.vat, children: isVatIncluded ? (jsx(FormattedMessage, { id: "Incl. VAT" })) : (jsx(FormattedMessage, { id: "Excl. VAT" })) })] })] }));
1870
+ }), children: originalPriceWithCurrency }), jsxs("div", { className: styles$Y['current-price-wrapper'], children: [jsxs("div", { className: styles$Y['current-price'], children: [jsx("span", { className: styles$Y.wholes, children: wholes }), jsx("span", { className: styles$Y.dot, children: "." }), jsx("span", { className: styles$Y.decimals, children: decimals })] }), isVatIncluded !== null && (jsx("span", { className: styles$Y.vat, children: isVatIncluded ? (jsx(FormattedMessage, { id: "Incl. VAT" })) : (jsx(FormattedMessage, { id: "Excl. VAT" })) }))] })] }));
1864
1871
  }
1865
1872
 
1866
1873
  var styles$X = {"product-sku":"product-sku-module-ITb8x"};
@@ -7901,11 +7908,17 @@ function Heading({ bold = true, children, className, italic, size = 'xxl', tag,
7901
7908
 
7902
7909
  var styles$M = {"dialog":"dialog-module-qKzgy","header":"dialog-module-ZnsAe","close":"dialog-module-Y7Tqg","footer":"dialog-module-y7Axm"};
7903
7910
 
7904
- function Footer({ close }) {
7905
- return (jsxs(Fragment, { children: [jsx(Button, { withArrow: true, color: "primary", size: "md", type: "submit", children: "Submit" }), jsx(Button, { color: "secondary", onClick: close, size: "md", variant: "outline", children: "Close" })] }));
7911
+ function Footer({ cancelLabel, close, submitLabel }) {
7912
+ return (jsxs(Fragment, { children: [jsx(Button, { withArrow: true, color: "primary", size: "md", type: "submit", children: jsx(FormattedMessage, { id: submitLabel }) }), jsx(Button, { color: "secondary", onClick: close, size: "md", variant: "outline", children: jsx(FormattedMessage, { id: cancelLabel }) })] }));
7906
7913
  }
7907
- function Dialog({ allowClose = true, children, className, dialogClassName, footer = Footer, hasCloseButton = true, hideTitle, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, onSubmit, shouldCloseOnInteractOutside, title, validationErrors, }) {
7908
- return (jsx(Modal, { className: clsx(styles$M['modal-overlay'], className), hasCloseButton: false, isDismissable: isDismissable, isFullScreen: isFullScreen, isKeyboardDismissDisabled: isKeyboardDismissDisabled, isOpen: isOpen, onOpenChange: onOpenChange, shouldCloseOnInteractOutside: shouldCloseOnInteractOutside, children: jsx(Dialog$1, { "aria-label": title, className: clsx(styles$M.dialog, dialogClassName), children: ({ close }) => (jsxs(Form, { className: styles$M.form, onSubmit: onSubmit || (e => e.preventDefault), validationErrors: validationErrors, children: [jsxs("header", { className: styles$M.header, children: [!hideTitle && (jsx(Heading, { className: styles$M.heading, size: "xs", children: title })), hasCloseButton && (jsx("div", { className: styles$M.close, children: jsx(IconButton, { color: "secondary", isDisabled: !allowClose, onClick: close, children: jsx(StrokeCloseboxIcon, {}) }) }))] }), jsx("div", { className: styles$M.content, children: children instanceof Function ? children({ close }) : children }), jsx("footer", { className: styles$M.footer, children: footer instanceof Function ? footer({ close }) : footer })] })) }) }));
7914
+ function Dialog({ allowClose = true, cancelLabel = 'Close', children, className, dialogClassName, footer = Footer, hasCloseButton = true, hideTitle, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, onSubmit, shouldCloseOnInteractOutside, submitLabel = 'Submit', title, validationErrors, }) {
7915
+ return (jsx(Modal, { className: clsx(styles$M['modal-overlay'], className), hasCloseButton: false, isDismissable: isDismissable, isFullScreen: isFullScreen, isKeyboardDismissDisabled: isKeyboardDismissDisabled, isOpen: isOpen, onOpenChange: onOpenChange, shouldCloseOnInteractOutside: shouldCloseOnInteractOutside, children: jsx(Dialog$1, { "aria-label": title, className: clsx(styles$M.dialog, dialogClassName), children: ({ close }) => (jsxs(Form, { className: styles$M.form, onSubmit: e => {
7916
+ e.preventDefault();
7917
+ e.stopPropagation();
7918
+ onSubmit?.(e);
7919
+ }, validationErrors: validationErrors, children: [jsxs("header", { className: styles$M.header, children: [!hideTitle && (jsx(Heading, { className: styles$M.heading, size: "xs", children: title })), hasCloseButton && (jsx("div", { className: styles$M.close, children: jsx(IconButton, { color: "secondary", isDisabled: !allowClose, onClick: close, children: jsx(StrokeCloseboxIcon, {}) }) }))] }), jsx("div", { className: styles$M.content, children: children instanceof Function ? children({ close }) : children }), jsx("footer", { className: styles$M.footer, children: footer instanceof Function
7920
+ ? footer({ cancelLabel, close, submitLabel })
7921
+ : footer })] })) }) }));
7909
7922
  }
7910
7923
 
7911
7924
  var styles$L = {"country-selector-dialog":"country-selector-dialog-module-mMJS0","content":"country-selector-dialog-module-z-ZqY","logo":"country-selector-dialog-module-7VjsF","intro":"country-selector-dialog-module-IdVDt","selects":"country-selector-dialog-module-Nvikf"};
@@ -0,0 +1,6 @@
1
+ import { OrderLineCardProps } from './orderline-card';
2
+ export interface ConnectedOrderLineProps extends Omit<OrderLineCardProps, 'addToCartButton' | 'favoriteButton'> {
3
+ onAddToCart?: VoidFunction;
4
+ onRemove?: (productId: string) => void;
5
+ }
6
+ export declare function ConnectedOrderLineCard({ id, onRemove, ...props }: ConnectedOrderLineProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ export interface ConnectedRemoveButtonProps {
2
+ onRemove: (productId: string) => void;
3
+ productId: string;
4
+ }
5
+ export declare function ConnectedRemoveButton({ onRemove: _onRemove, productId, }: ConnectedRemoveButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,25 @@
1
+ import { ReactElement } from 'react';
2
+ import { ImageSource } from 'shared/model/image';
3
+ import type { ProductTotalPrice as ProductTotalPriceType } from 'shared/model/price';
4
+ export interface BaseOrderLineCardProps {
5
+ deliveryDate?: Date;
6
+ href: string;
7
+ id: string;
8
+ image: ImageSource;
9
+ price: ProductTotalPriceType;
10
+ readonly: boolean;
11
+ sku: string;
12
+ tags?: string[];
13
+ title: string;
14
+ }
15
+ export interface InteractiveOrderLineCardProps extends BaseOrderLineCardProps {
16
+ addToCartButton: ReactElement;
17
+ readonly: false;
18
+ removeButton: ReactElement;
19
+ }
20
+ export interface ReadonlyOrderLineCardProps extends BaseOrderLineCardProps {
21
+ quantity: number;
22
+ readonly: true;
23
+ }
24
+ export type OrderLineCardProps = InteractiveOrderLineCardProps | ReadonlyOrderLineCardProps;
25
+ export declare function OrderLineCard(props: OrderLineCardProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,46 @@
1
+ import type { StoryObj } from '@storybook/react';
2
+ import { OrderLineCard } from './orderline-card';
3
+ declare const meta: {
4
+ component: typeof OrderLineCard;
5
+ decorators: ((Story: import("@storybook/csf").PartialStoryFn<import("@storybook/react").ReactRenderer, {
6
+ addToCartButton: React.ReactElement;
7
+ readonly: false;
8
+ removeButton: React.ReactElement;
9
+ deliveryDate?: Date | undefined;
10
+ href: string;
11
+ id: string;
12
+ image: import("../../shared/model/image").ImageSource;
13
+ price: import("../../shared/model/price").ProductTotalPrice;
14
+ sku: string;
15
+ tags?: string[] | undefined;
16
+ title: string;
17
+ } | {
18
+ quantity: number;
19
+ readonly: true;
20
+ deliveryDate?: Date | undefined;
21
+ href: string;
22
+ id: string;
23
+ image: import("../../shared/model/image").ImageSource;
24
+ price: import("../../shared/model/price").ProductTotalPrice;
25
+ sku: string;
26
+ tags?: string[] | undefined;
27
+ title: string;
28
+ }>) => import("react/jsx-runtime").JSX.Element)[];
29
+ parameters: {
30
+ layout: string;
31
+ };
32
+ tags: string[];
33
+ title: string;
34
+ };
35
+ export default meta;
36
+ type Story = StoryObj<typeof OrderLineCard>;
37
+ export declare const Default: Story;
38
+ export declare const Small: Story;
39
+ export declare const Medium: Story;
40
+ export declare const Large: Story;
41
+ export declare const LongTitle: Story;
42
+ export declare const BigPrice: Story;
43
+ export declare const WithoutTags: Story;
44
+ export declare const ReadOnly: Story;
45
+ export declare const ReadOnlyNoTag: Story;
46
+ export declare const Connected: Story;
@@ -0,0 +1,5 @@
1
+ export interface DeliveryTimeProps {
2
+ className?: string;
3
+ deliveryDate: Date;
4
+ }
5
+ export declare function DeliveryTime({ className, deliveryDate }: DeliveryTimeProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import type { StoryObj } from '@storybook/react';
2
+ import { DeliveryTime } from './delivery-time';
3
+ declare const meta: {
4
+ component: typeof DeliveryTime;
5
+ parameters: {
6
+ layout: string;
7
+ };
8
+ tags: string[];
9
+ title: string;
10
+ };
11
+ export default meta;
12
+ type Story = StoryObj<typeof meta>;
13
+ export declare const Default: Story;
@@ -1,7 +1,8 @@
1
1
  export interface ProductPriceProps {
2
2
  className?: string;
3
- isVatIncluded: boolean;
3
+ isVatIncluded: boolean | null;
4
4
  originalPrice: number;
5
5
  price: number;
6
+ pricePerUnit?: number;
6
7
  }
7
8
  export declare function ProductPrice({ className, isVatIncluded, originalPrice, price, }: ProductPriceProps): import("react/jsx-runtime").JSX.Element | undefined;
@@ -0,0 +1,7 @@
1
+ export interface ProductTotalPriceProps {
2
+ className?: string;
3
+ originalTotalPrice: number;
4
+ pricePerUnit?: number;
5
+ totalPrice: number;
6
+ }
7
+ export declare function ProductTotalPrice({ className, originalTotalPrice: originalPrice, pricePerUnit, totalPrice, }: ProductTotalPriceProps): import("react/jsx-runtime").JSX.Element | undefined;
@@ -0,0 +1,14 @@
1
+ import type { StoryObj } from '@storybook/react';
2
+ import { ProductTotalPrice } from './product-total-price';
3
+ declare const meta: {
4
+ component: typeof ProductTotalPrice;
5
+ parameters: {
6
+ layout: string;
7
+ };
8
+ tags: string[];
9
+ title: string;
10
+ };
11
+ export default meta;
12
+ type Story = StoryObj<typeof meta>;
13
+ export declare const WithoutOriginalTotalPrice: Story;
14
+ export declare const WithOriginalTotalPrice: Story;
@@ -1 +1 @@
1
- export type TranslationId = "'{0}' in all products" | "Try 'Search' and try to find the product you're looking for" | "Unfortnately, We found no articles for your search '{0}'" | ' to your account to manage your lists.' | 'Add to list' | 'An unexpected error occured' | 'Are you looking for information about our service? Please visit our customer support page' | 'Cancel' | 'Chosen filters' | 'Clear filters' | 'Clear' | 'Continue shopping' | 'Cost overview' | 'Country' | 'Create new list' | 'create account' | 'Double check your spelling' | 'Downloads' | 'Excl. VAT' | 'Explore by categories' | 'Exploring our products by category' | 'Features' | 'Fulfillment method' | 'Hide filters' | 'Incl. VAT' | 'Includes' | 'Language' | 'List name already exists' | 'New list name' | 'Order number' | 'Please Sign In' | 'Popular searches' | 'Print' | 'Product Features' | 'Products' | 'Quick access' | 'Recent searches' | 'Recently viewed' | 'Searching again using more general terms' | 'See all results' | 'Select a list' | 'Shop more efficiently and quicker with a favorites list' | 'Easily add your favorite products' | 'Your favorites are available on multiple devices' | 'Save' | 'Share your favorite list with others' | 'Shipping and handling' | 'Show all' | 'Show filters' | 'Show less' | 'Show' | 'Sorry, there are no products found' | 'Sorry, we could not find matches for' | 'Sort by' | 'Specifications' | 'Submit' | 'Subtotal' | 'Suggestions' | 'The product has been added to your cart.' | 'The product has been updated in your cart.' | 'The product has been removed from your cart.' | 'Unable to add the product to your cart.' | 'Unable to update the product in your cart.' | 'Unable to remove the product from your cart.' | 'Try another search' | 'Total' | 'Use fewer keywords' | 'VAT' | 'Welcome to Sonic Equipment. Please choose your country and language below.' | 'What are you searching for?' | 'You could try checking the spelling of your search query' | 'You could try exploring our products by category' | 'You could try' | 'You must ' | 'article' | 'articles' | 'facet.categories' | 'facet.height' | 'facet.weight' | 'of' | 'sign in' | 'sort.newest' | 'sort.price_asc' | 'sort.price_desc' | 'sort.relevance' | 'tag.limited' | 'tag.new';
1
+ export type TranslationId = "'{0}' in all products" | "Try 'Search' and try to find the product you're looking for" | "Unfortnately, We found no articles for your search '{0}'" | ' to your account to manage your lists.' | 'Add to list' | 'Amount: {0}' | 'An unexpected error occured' | 'Are you looking for information about our service? Please visit our customer support page' | 'Are you sure you want to remove all items from your cart?' | 'Are you sure you want to remove this item from your cart?' | 'Cancel' | 'Chosen filters' | 'Clear filters' | 'Clear' | 'Continue' | 'Continue shopping' | 'Cost overview' | 'Country' | 'Create new list' | 'create account' | 'Delivery expected in {0} {1}' | 'Double check your spelling' | 'Downloads' | 'Excl. VAT' | 'Explore by categories' | 'Exploring our products by category' | 'Features' | 'Fulfillment method' | 'Hide filters' | 'Incl. VAT' | 'Includes' | 'Language' | 'List name already exists' | 'New list name' | 'Order number' | 'pc' | 'Please Sign In' | 'Popular searches' | 'Print' | 'Product Features' | 'Products' | 'Product' | 'Quick access' | 'Recent searches' | 'Recently viewed' | 'Remove all' | 'Searching again using more general terms' | 'See all results' | 'Select a list' | 'Shop more efficiently and quicker with a favorites list' | 'Easily add your favorite products' | 'Your favorites are available on multiple devices' | 'Save' | 'Share your favorite list with others' | 'Shipping and handling' | 'Show all' | 'Show filters' | 'Show less' | 'Show' | 'Sorry, there are no products found' | 'Sorry, we could not find matches for' | 'Sort by' | 'Specifications' | 'Submit' | 'Subtotal' | 'Suggestions' | 'The product has been added to your cart.' | 'The product has been updated in your cart.' | 'The product has been removed from your cart.' | 'Unable to add the product to your cart.' | 'Unable to update the product in your cart.' | 'Unable to remove the product from your cart.' | 'Try another search' | 'Total' | 'Use fewer keywords' | 'VAT' | 'Welcome to Sonic Equipment. Please choose your country and language below.' | 'What are you searching for?' | 'You could try checking the spelling of your search query' | 'You could try exploring our products by category' | 'You could try' | 'You must ' | 'article' | 'articles' | 'facet.categories' | 'facet.height' | 'facet.weight' | 'of' | 'sign in' | 'sort.newest' | 'sort.price_asc' | 'sort.price_desc' | 'sort.relevance' | 'tag.limited' | 'tag.new';
@@ -1,7 +1,13 @@
1
1
  import { TranslationId } from './translation-id';
2
- export type FormattedMessageFunction = (id: TranslationId, options?: {
3
- fallbackValue?: string;
4
- optional?: boolean;
5
- replacementValues?: Record<string, string>;
6
- }) => string;
2
+ export interface FormattedMessageFunction {
3
+ (id: TranslationId, options?: {
4
+ fallbackValue?: string;
5
+ optional?: boolean;
6
+ replacementValues?: Record<string, string>;
7
+ }): string;
8
+ pluralize: {
9
+ (translationId: string, count: number): string;
10
+ (translationIdPrefix: string, translationId: string, count: number): string;
11
+ };
12
+ }
7
13
  export declare function useFormattedMessage(): FormattedMessageFunction;
@@ -0,0 +1,7 @@
1
+ import { ReactNode } from 'react';
2
+ interface OrderLineListProps {
3
+ children?: ReactNode;
4
+ onRemoveAll?: () => void;
5
+ }
6
+ export declare function OrderLineList({ children, onRemoveAll }: OrderLineListProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { StoryObj } from '@storybook/react';
2
+ import { OrderLineList } from './orderline-list';
3
+ declare const meta: {
4
+ component: typeof OrderLineList;
5
+ parameters: {
6
+ layout: string;
7
+ };
8
+ title: string;
9
+ };
10
+ export default meta;
11
+ type Story = StoryObj<typeof meta>;
12
+ export declare const Small: Story;
13
+ export declare const Medium: Story;
14
+ export declare const Large: Story;
15
+ export declare const Connected: Story;
@@ -0,0 +1,10 @@
1
+ interface ConfirmationDialogProps {
2
+ cancelLabel?: string;
3
+ isOpen: boolean;
4
+ onCancel: VoidFunction;
5
+ onConfirm: VoidFunction;
6
+ submitLabel?: string;
7
+ title: string;
8
+ }
9
+ export declare function ConfirmationDialog({ cancelLabel, isOpen, onCancel, onConfirm, submitLabel, title, }: ConfirmationDialogProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,19 @@
1
+ import type { StoryObj } from '@storybook/react';
2
+ import { ConfirmationDialog } from './confirmation-dialog';
3
+ declare const meta: {
4
+ argTypes: {
5
+ isOpen: {
6
+ control: {
7
+ type: "boolean";
8
+ };
9
+ };
10
+ };
11
+ component: typeof ConfirmationDialog;
12
+ parameters: {
13
+ layout: string;
14
+ };
15
+ title: string;
16
+ };
17
+ export default meta;
18
+ type Story = StoryObj<typeof meta>;
19
+ export declare const Default: Story;
@@ -3,17 +3,22 @@ import { Form as AriaForm } from 'react-aria-components';
3
3
  import { ModalProps } from 'modals/modal/modal';
4
4
  interface DialogProps extends Omit<ModalProps, 'children'> {
5
5
  allowClose?: boolean;
6
- children: ReactNode | ((props: {
6
+ cancelLabel?: string;
7
+ children?: ReactNode | ((props: {
7
8
  close: VoidFunction;
8
9
  }) => ReactNode);
9
10
  dialogClassName?: string;
10
- footer?: ReactNode | ((props: {
11
- close: VoidFunction;
12
- }) => ReactNode);
11
+ footer?: ReactNode | ((props: DialogFooterProps) => ReactNode);
13
12
  hideTitle?: boolean;
14
13
  onSubmit?: (e: React.FormEvent<HTMLFormElement>) => void;
14
+ submitLabel?: string;
15
15
  title: string;
16
16
  validationErrors?: ComponentProps<typeof AriaForm>['validationErrors'];
17
17
  }
18
- export declare function Dialog({ allowClose, children, className, dialogClassName, footer, hasCloseButton, hideTitle, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, onSubmit, shouldCloseOnInteractOutside, title, validationErrors, }: DialogProps): import("react/jsx-runtime").JSX.Element;
18
+ interface DialogFooterProps {
19
+ cancelLabel: string;
20
+ close: VoidFunction;
21
+ submitLabel: string;
22
+ }
23
+ export declare function Dialog({ allowClose, cancelLabel, children, className, dialogClassName, footer, hasCloseButton, hideTitle, isDismissable, isFullScreen, isKeyboardDismissDisabled, isOpen, onOpenChange, onSubmit, shouldCloseOnInteractOutside, submitLabel, title, validationErrors, }: DialogProps): import("react/jsx-runtime").JSX.Element;
19
24
  export {};
@@ -1,3 +1,6 @@
1
- import { FetchAnnouncementsArgs } from 'shared/api/bff/services/bff-service';
2
1
  import { Announcement } from 'shared/model/announcement';
2
+ interface FetchAnnouncementsArgs {
3
+ languageCode: string;
4
+ }
3
5
  export declare function useFetchAnnouncements({ languageCode, }: FetchAnnouncementsArgs): import("@tanstack/react-query").UseQueryResult<Announcement[], Error>;
6
+ export {};
@@ -1,6 +1,6 @@
1
1
  declare const features: {
2
2
  readonly language: "language";
3
- readonly pdpv1: "pdpV1";
3
+ readonly pdp: "pdpV2";
4
4
  readonly plpv1: "plpV1";
5
5
  readonly searchv1: "searchV1";
6
6
  };
@@ -3,3 +3,8 @@ export interface ProductPrice {
3
3
  originalPrice: number;
4
4
  price: number;
5
5
  }
6
+ export interface ProductTotalPrice {
7
+ originalTotalPrice: number;
8
+ pricePerUnit?: number;
9
+ totalPrice: number;
10
+ }
@@ -0,0 +1,11 @@
1
+ export type DateUnit = 'day' | 'week' | 'month';
2
+ export type DateUnitObject = {
3
+ number: number;
4
+ unit: DateUnit;
5
+ };
6
+ export type DateThreshold = {
7
+ dateUnitObject: DateUnitObject;
8
+ numberOfDays: number;
9
+ };
10
+ export declare function getDateUnitObject(date: Date): DateUnitObject;
11
+ export declare function convertDateUnitToPluralOrSingle(unit: DateUnit, number: number): 'day' | 'days' | 'week' | 'weeks' | 'month' | 'months';
@@ -0,0 +1 @@
1
+ export {};
package/dist/styles.css CHANGED
@@ -952,6 +952,7 @@
952
952
 
953
953
  .product-price-module-oIU1K {
954
954
  --current-price-color: var(--color-brand-black);
955
+ --original-price-font-size: var(--font-size-18);
955
956
  --current-price-font-style: normal;
956
957
  --font-size-wholes: var(--price-font-size-wholes, var(--font-size-36));
957
958
  --font-size-decimals: var(--price-font-size-decimals, var(--font-size-24));
@@ -964,7 +965,7 @@
964
965
  .product-price-module-oIU1K .product-price-module-til0s {
965
966
  padding-left: var(--space-4);
966
967
  color: var(--color-brand-dark-gray);
967
- font-size: var(--font-size-18);
968
+ font-size: var(--original-price-font-size);
968
969
  font-weight: var(--font-weight-bold);
969
970
  text-decoration: line-through;
970
971
  }
@@ -985,14 +986,14 @@
985
986
  position: relative;
986
987
  display: flex;
987
988
  color: var(--current-price-color);
988
- font-size: var(--font-size-36);
989
+ font-size: var(--font-size-wholes);
989
990
  font-style: var(--current-price-font-style);
990
991
  font-weight: var(--font-weight-black);
991
992
  }
992
993
 
993
994
  .product-price-module-oIU1K .product-price-module-pvy2w .product-price-module-GCw07,
994
995
  .product-price-module-oIU1K .product-price-module-pvy2w .product-price-module-N56iV {
995
- font-size: var(--font-size-wholes);
996
+ font-size: inherit;
996
997
  font-weight: inherit;
997
998
  }
998
999
 
@@ -1004,6 +1005,7 @@
1004
1005
  font-weight: inherit;
1005
1006
  }
1006
1007
 
1008
+ .product-price-module-oIU1K .product-price-module-syhum,
1007
1009
  .product-price-module-oIU1K .product-price-module-96DoG {
1008
1010
  color: var(--color-brand-dark-gray);
1009
1011
  font-size: var(--font-size-12);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonic-equipment/ui",
3
- "version": "0.0.112",
3
+ "version": "0.0.113",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -36,7 +36,8 @@
36
36
  "start": "http-server ./storybook-static",
37
37
  "stylelint": "stylelint --config .stylelintrc.cjs \"src/**/*.css\"",
38
38
  "stylelint:fix": "stylelint --config .stylelintrc.cjs \"src/**/*.css\" --formatter verbose --fix",
39
- "test:all": "npx concurrently -g --names \"TSC,ESLINT,STYLELINT\" -c auto --kill-others-on-fail \"npm run test:types\" \"npm run lint\" \"npm run stylelint\"",
39
+ "test:all": "npx concurrently -g --names \"TSC,VITEST,ESLINT,STYLELINT\" -c auto --kill-others-on-fail \"npm run test:types\" \"npm run test:unit\" \"npm run lint\" \"npm run stylelint\"",
40
+ "test:unit": "vitest run",
40
41
  "test:types": "tsc --noEmit --pretty false",
41
42
  "update-packages": "npx npm-check-updates -u"
42
43
  },
@@ -69,6 +70,7 @@
69
70
  "@storybook/test": "8.4.2",
70
71
  "@types/js-cookie": "3.0.6",
71
72
  "@types/node": "22.9.0",
73
+ "@types/postcss-import": "14.0.3",
72
74
  "@types/react": "18.3.12",
73
75
  "@types/react-dom": "18.3.1",
74
76
  "@typescript-eslint/eslint-plugin": "8.13.0",
@@ -113,7 +115,8 @@
113
115
  "stylelint-config-standard": "36.0.1",
114
116
  "typescript": "5.6.3",
115
117
  "vite": "5.4.10",
116
- "vite-tsconfig-paths": "5.1.0"
118
+ "vite-tsconfig-paths": "5.1.0",
119
+ "vitest": "2.1.5"
117
120
  },
118
121
  "dependencies": {
119
122
  "@algolia/autocomplete-core": "1.17.7",