@workos-inc/widgets 1.7.0-pre.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,7 +41,7 @@ var import_clsx = __toESM(require("clsx"), 1);
41
41
  var import_utils = require("./utils.js");
42
42
  var import_generic_error = require("./generic-error.js");
43
43
  var import_elements = require("./elements.js");
44
- var import_react_query = require("@tanstack/react-query");
44
+ var import_utils2 = require("../utils.js");
45
45
  const OrganizationSwitcher = ({
46
46
  organizations,
47
47
  switchToOrganization,
@@ -54,8 +54,7 @@ const OrganizationSwitcher = ({
54
54
  const currentOrganization = organizations.find(
55
55
  (organization) => organization.current
56
56
  );
57
- const queryClient = (0, import_react_query.useQueryClient)();
58
- const invalidateAllWidgets = () => queryClient.invalidateQueries({ queryKey: ["/_widgets/"] });
57
+ const invalidateAllWidgets = (0, import_utils2.unstable_useWidgetsInvalidator)();
59
58
  if (!currentOrganization) {
60
59
  return null;
61
60
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/organization-switcher.tsx"],"sourcesContent":["\"use client\";\n\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport {\n Box,\n ChevronDownIcon,\n Flex,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport type { OrganizationInfo } from \"../api/endpoint.js\";\nimport cx from \"clsx\";\nimport {\n getDomProps,\n isPromiseLike,\n type WidgetRootDomProps,\n type WidgetRootState,\n} from \"./utils.js\";\nimport { getErrorMessage } from \"./generic-error.js\";\nimport {\n Button,\n type ButtonProps,\n Skeleton,\n DropdownMenu,\n} from \"./elements.js\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\ntype OrganizationSwitcherVariant = \"ghost\" | \"outline\";\n\n// Rename all uses of `org` to `organization`\ninterface OrganizationSwitcherPassthroughProps extends WidgetRootDomProps {\n switchToOrganization: ({\n organizationId,\n }: {\n organizationId: string;\n }) => void | Promise<void>;\n // Simple props to affect the overall style\n variant?: OrganizationSwitcherVariant;\n organizationLabel?: string | null;\n children?: React.ReactNode;\n /**\n * Choose where to truncate organization name in the trigger and dropdown\n * items.\n *\n * - `right`: Truncate the right side of the organization name\n * - `middle`: Truncate the middle of the organization name, trying to keep\n * words whole\n */\n truncateBehavior?: \"right\" | \"middle\";\n}\n\ninterface OrganizationSwitcherProps\n extends OrganizationSwitcherPassthroughProps {\n organizations: OrganizationInfo[];\n}\n\nconst OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({\n organizations,\n switchToOrganization,\n variant,\n organizationLabel = \"Organizations\",\n truncateBehavior = \"right\",\n children,\n ...domProps\n}) => {\n const currentOrganization = organizations.find(\n (organization) => organization.current,\n );\n const queryClient = useQueryClient();\n const invalidateAllWidgets = () =>\n queryClient.invalidateQueries({ queryKey: [\"/_widgets/\"] });\n\n // TODO: Possible if the user has no organizations - we should figure out what\n // to do in this case\n if (!currentOrganization) {\n return null;\n }\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <Button\n variant=\"secondary\"\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"resolved\", {\n ...domProps,\n // TODO: Remove `OrganizationSwitcherTrigger` in the next major\n // version. This should follow conventions of all other widgets\n // using classnames in getWidgetRootDomProps.\n className: cx(domProps.className, \"OrganizationSwitcherTrigger\"),\n })}\n >\n <Flex\n align=\"center\"\n justify=\"between\"\n gap=\"2\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n minWidth=\"0\"\n >\n <TruncatedOrganizationName\n organizationName={currentOrganization.name}\n truncateBehavior={truncateBehavior}\n />\n <Flex asChild flexShrink=\"0\">\n <DropdownMenu.TriggerIcon />\n </Flex>\n </Flex>\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Group>\n {organizationLabel ? (\n <DropdownMenu.Label>\n <Text>{organizationLabel}</Text>\n </DropdownMenu.Label>\n ) : null}\n {organizations.map((organization) => (\n <Flex\n key={organization.id}\n asChild\n pr=\"2\"\n maxWidth=\"280px\"\n minWidth=\"180px\"\n >\n <DropdownMenu.Item\n onClick={() => {\n if (organization.id !== currentOrganization.id) {\n const result = switchToOrganization({\n organizationId: organization.id,\n });\n if (isPromiseLike(result)) {\n result.then(invalidateAllWidgets);\n } else {\n invalidateAllWidgets();\n }\n }\n }}\n >\n <Flex\n justify=\"between\"\n align=\"center\"\n gap=\"4\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n >\n <TruncatedOrganizationName\n organizationName={organization.name}\n truncateBehavior={truncateBehavior}\n />\n {organization.current && (\n <VisuallyHidden> (current)</VisuallyHidden>\n )}\n <Flex\n aria-hidden\n align=\"center\"\n justify=\"center\"\n flexShrink=\"0\"\n >\n {organization.current ? (\n <CheckIcon width=\"18px\" height=\"18px\" />\n ) : (\n // make the extra space for\n <Box width=\"18px\" height=\"18px\" />\n )}\n </Flex>\n </Flex>\n </DropdownMenu.Item>\n </Flex>\n ))}\n </DropdownMenu.Group>\n {children}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n};\n\ninterface OrganizationSwitcherLoadingProps extends WidgetRootDomProps {\n variant?: OrganizationSwitcherVariant;\n}\n\nconst OrganizationSwitcherLoading: React.FC<\n OrganizationSwitcherLoadingProps\n> = ({ variant, ...props }: OrganizationSwitcherLoadingProps) => {\n return (\n // Always need DropdownMenu.Root to wrap children than may include\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"loading\", props)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Skeleton>\n <Text>Loading...</Text>\n </Skeleton>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n};\n\ninterface OrganizationSwitcherErrorProps extends WidgetRootDomProps {\n error: unknown;\n variant?: OrganizationSwitcherVariant;\n}\n\nfunction OrganizationSwitcherError({\n error,\n variant,\n ...domProps\n}: OrganizationSwitcherErrorProps) {\n const { heading } = getErrorMessage(error);\n\n return (\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"error\", domProps)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Text>{heading}</Text>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n}\n\nconst MAX_TRUNCATED_SUFFIX_LENGTH = 10;\nconst MIN_TRUNCATED_SUFFIX_LENGTH = 3;\n\nconst WHITE_SPACE_REGEX = /\\s/;\n\nconst getSplitPosition = (organizationName: string) => {\n if (organizationName.length <= MAX_TRUNCATED_SUFFIX_LENGTH) {\n return organizationName.length;\n }\n\n for (\n let i = organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n i < organizationName.length - MIN_TRUNCATED_SUFFIX_LENGTH;\n i++\n ) {\n if (WHITE_SPACE_REGEX.test(organizationName[i - 1])) {\n return i;\n }\n }\n\n return organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n};\n\nconst splitOrganizationName = (organizationName: string) => {\n const splitPosition = getSplitPosition(organizationName);\n return [\n organizationName.slice(0, splitPosition),\n organizationName.slice(splitPosition),\n ];\n};\n\nconst TruncatedOrganizationName = ({\n organizationName,\n truncateBehavior,\n}: {\n organizationName: string;\n truncateBehavior: \"right\" | \"middle\";\n}) => {\n if (truncateBehavior === \"right\") {\n return <Text truncate>{organizationName}</Text>;\n }\n\n const [organizationNameLeft, organizationNameRight] =\n splitOrganizationName(organizationName);\n\n return (\n <Flex overflow=\"hidden\">\n <VisuallyHidden>\n <Text>{organizationName}</Text>\n </VisuallyHidden>\n <Text aria-hidden truncate style={{ whiteSpace: \"pre\" }}>\n {organizationNameLeft}\n </Text>\n <Text aria-hidden>{organizationNameRight}</Text>\n </Flex>\n );\n};\n\nfunction mapVariantProps(variant?: OrganizationSwitcherVariant): ButtonProps {\n const variantProps: ButtonProps = {};\n // Passing `undefined` to the variant prop will result in overrides to props we\n // set internally. This should be addressed in Radix Themes, but we can\n // explicitly set it only when it's provided and _not_ undefined.\n if (variant) {\n variantProps.unsafe_radixVariant = variant;\n }\n return variantProps;\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"organization-switcher\",\n widgetState: state,\n });\n}\n\nexport type {\n OrganizationSwitcherProps,\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherErrorProps,\n /** @internal */\n OrganizationSwitcherPassthroughProps,\n};\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n OrganizationSwitcherError,\n};\n"],"mappings":"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","names":["cx"]}
1
+ {"version":3,"sources":["../../../src/lib/organization-switcher.tsx"],"sourcesContent":["\"use client\";\n\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport {\n Box,\n ChevronDownIcon,\n Flex,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport type { OrganizationInfo } from \"../api/endpoint.js\";\nimport cx from \"clsx\";\nimport {\n getDomProps,\n isPromiseLike,\n type WidgetRootDomProps,\n type WidgetRootState,\n} from \"./utils.js\";\nimport { getErrorMessage } from \"./generic-error.js\";\nimport {\n Button,\n type ButtonProps,\n Skeleton,\n DropdownMenu,\n} from \"./elements.js\";\nimport { unstable_useWidgetsInvalidator as useWidgetsInvalidator } from \"../utils.js\";\n\ntype OrganizationSwitcherVariant = \"ghost\" | \"outline\";\n\n// Rename all uses of `org` to `organization`\ninterface OrganizationSwitcherPassthroughProps extends WidgetRootDomProps {\n switchToOrganization: ({\n organizationId,\n }: {\n organizationId: string;\n }) => void | Promise<void>;\n // Simple props to affect the overall style\n variant?: OrganizationSwitcherVariant;\n organizationLabel?: string | null;\n children?: React.ReactNode;\n /**\n * Choose where to truncate organization name in the trigger and dropdown\n * items.\n *\n * - `right`: Truncate the right side of the organization name\n * - `middle`: Truncate the middle of the organization name, trying to keep\n * words whole\n */\n truncateBehavior?: \"right\" | \"middle\";\n}\n\ninterface OrganizationSwitcherProps\n extends OrganizationSwitcherPassthroughProps {\n organizations: OrganizationInfo[];\n}\n\nconst OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({\n organizations,\n switchToOrganization,\n variant,\n organizationLabel = \"Organizations\",\n truncateBehavior = \"right\",\n children,\n ...domProps\n}) => {\n const currentOrganization = organizations.find(\n (organization) => organization.current,\n );\n const invalidateAllWidgets = useWidgetsInvalidator();\n\n // TODO: Possible if the user has no organizations - we should figure out what\n // to do in this case\n if (!currentOrganization) {\n return null;\n }\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <Button\n variant=\"secondary\"\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"resolved\", {\n ...domProps,\n // TODO: Remove `OrganizationSwitcherTrigger` in the next major\n // version. This should follow conventions of all other widgets\n // using classnames in getWidgetRootDomProps.\n className: cx(domProps.className, \"OrganizationSwitcherTrigger\"),\n })}\n >\n <Flex\n align=\"center\"\n justify=\"between\"\n gap=\"2\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n minWidth=\"0\"\n >\n <TruncatedOrganizationName\n organizationName={currentOrganization.name}\n truncateBehavior={truncateBehavior}\n />\n <Flex asChild flexShrink=\"0\">\n <DropdownMenu.TriggerIcon />\n </Flex>\n </Flex>\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Group>\n {organizationLabel ? (\n <DropdownMenu.Label>\n <Text>{organizationLabel}</Text>\n </DropdownMenu.Label>\n ) : null}\n {organizations.map((organization) => (\n <Flex\n key={organization.id}\n asChild\n pr=\"2\"\n maxWidth=\"280px\"\n minWidth=\"180px\"\n >\n <DropdownMenu.Item\n onClick={() => {\n if (organization.id !== currentOrganization.id) {\n const result = switchToOrganization({\n organizationId: organization.id,\n });\n if (isPromiseLike(result)) {\n result.then(invalidateAllWidgets);\n } else {\n invalidateAllWidgets();\n }\n }\n }}\n >\n <Flex\n justify=\"between\"\n align=\"center\"\n gap=\"4\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n >\n <TruncatedOrganizationName\n organizationName={organization.name}\n truncateBehavior={truncateBehavior}\n />\n {organization.current && (\n <VisuallyHidden> (current)</VisuallyHidden>\n )}\n <Flex\n aria-hidden\n align=\"center\"\n justify=\"center\"\n flexShrink=\"0\"\n >\n {organization.current ? (\n <CheckIcon width=\"18px\" height=\"18px\" />\n ) : (\n // make the extra space for\n <Box width=\"18px\" height=\"18px\" />\n )}\n </Flex>\n </Flex>\n </DropdownMenu.Item>\n </Flex>\n ))}\n </DropdownMenu.Group>\n {children}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n};\n\ninterface OrganizationSwitcherLoadingProps extends WidgetRootDomProps {\n variant?: OrganizationSwitcherVariant;\n}\n\nconst OrganizationSwitcherLoading: React.FC<\n OrganizationSwitcherLoadingProps\n> = ({ variant, ...props }: OrganizationSwitcherLoadingProps) => {\n return (\n // Always need DropdownMenu.Root to wrap children than may include\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"loading\", props)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Skeleton>\n <Text>Loading...</Text>\n </Skeleton>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n};\n\ninterface OrganizationSwitcherErrorProps extends WidgetRootDomProps {\n error: unknown;\n variant?: OrganizationSwitcherVariant;\n}\n\nfunction OrganizationSwitcherError({\n error,\n variant,\n ...domProps\n}: OrganizationSwitcherErrorProps) {\n const { heading } = getErrorMessage(error);\n\n return (\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"error\", domProps)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Text>{heading}</Text>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n}\n\nconst MAX_TRUNCATED_SUFFIX_LENGTH = 10;\nconst MIN_TRUNCATED_SUFFIX_LENGTH = 3;\n\nconst WHITE_SPACE_REGEX = /\\s/;\n\nconst getSplitPosition = (organizationName: string) => {\n if (organizationName.length <= MAX_TRUNCATED_SUFFIX_LENGTH) {\n return organizationName.length;\n }\n\n for (\n let i = organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n i < organizationName.length - MIN_TRUNCATED_SUFFIX_LENGTH;\n i++\n ) {\n if (WHITE_SPACE_REGEX.test(organizationName[i - 1])) {\n return i;\n }\n }\n\n return organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n};\n\nconst splitOrganizationName = (organizationName: string) => {\n const splitPosition = getSplitPosition(organizationName);\n return [\n organizationName.slice(0, splitPosition),\n organizationName.slice(splitPosition),\n ];\n};\n\nconst TruncatedOrganizationName = ({\n organizationName,\n truncateBehavior,\n}: {\n organizationName: string;\n truncateBehavior: \"right\" | \"middle\";\n}) => {\n if (truncateBehavior === \"right\") {\n return <Text truncate>{organizationName}</Text>;\n }\n\n const [organizationNameLeft, organizationNameRight] =\n splitOrganizationName(organizationName);\n\n return (\n <Flex overflow=\"hidden\">\n <VisuallyHidden>\n <Text>{organizationName}</Text>\n </VisuallyHidden>\n <Text aria-hidden truncate style={{ whiteSpace: \"pre\" }}>\n {organizationNameLeft}\n </Text>\n <Text aria-hidden>{organizationNameRight}</Text>\n </Flex>\n );\n};\n\nfunction mapVariantProps(variant?: OrganizationSwitcherVariant): ButtonProps {\n const variantProps: ButtonProps = {};\n // Passing `undefined` to the variant prop will result in overrides to props we\n // set internally. This should be addressed in Radix Themes, but we can\n // explicitly set it only when it's provided and _not_ undefined.\n if (variant) {\n variantProps.unsafe_radixVariant = variant;\n }\n return variantProps;\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"organization-switcher\",\n widgetState: state,\n });\n}\n\nexport type {\n OrganizationSwitcherProps,\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherErrorProps,\n /** @internal */\n OrganizationSwitcherPassthroughProps,\n};\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n OrganizationSwitcherError,\n};\n"],"mappings":"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","names":["import_utils","useWidgetsInvalidator","cx"]}
@@ -89,7 +89,7 @@ function isErrorLike(value) {
89
89
  return isObjectLike(value) && typeof value.message === "string";
90
90
  }
91
91
  function isPromiseLike(value) {
92
- return typeof value === "object" && value !== null && "then" in value;
92
+ return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
93
93
  }
94
94
  async function parseErrorResponse(response) {
95
95
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils.ts"],"sourcesContent":["import { Member } from \"../api/endpoint.js\";\nimport Bowser from \"bowser\";\nimport cx from \"clsx\";\nimport {\n WIDGETS_CLASS_NAMESPACE,\n WIDGETS_DATA_ATTRIBUTE_NAMESPACE,\n} from \"./constants.js\";\nimport type { Elements } from \"./elements.js\";\n\nexport const canUseDOM = !!(\n typeof window !== \"undefined\" &&\n window.document &&\n window.document.createElement\n);\n\nexport function getBestName({\n firstName,\n lastName,\n}: Pick<Member, \"firstName\" | \"lastName\">) {\n return [firstName, lastName].filter(Boolean).join(\" \") || null;\n}\n\nexport function getComparativeReadableDate(\n now: Date,\n then: Date,\n options?: { timeZone?: string },\n): string {\n const timeSince = now.getTime() - then.getTime();\n\n // Has it been less than a minute?\n if (timeSince < 60_000) {\n return \"Just now\";\n }\n\n // Has it been less than an hour?\n if (timeSince < 3_600_000) {\n const timePassed = Math.floor(timeSince / 60_000);\n return timePassed === 1 ? \"1 minute ago\" : `${timePassed} minutes ago`;\n }\n\n // Has it been less than a day?\n if (timeSince < 86_400_000) {\n const timePassed = Math.floor(timeSince / 3_600_000);\n return timePassed === 1 ? \"1 hour ago\" : `${timePassed} hours ago`;\n }\n\n // Has it been less than a week?\n if (timeSince < 604_800_000) {\n const timePassed = Math.floor(timeSince / 86_400_000);\n return timePassed === 1 ? \"1 day ago\" : `${timePassed} days ago`;\n }\n\n // Has it been less than a month?\n if (timeSince < 2_592_000_000) {\n const timePassed = Math.floor(timeSince / 604_800_000);\n return timePassed === 1 ? \"1 week ago\" : `${timePassed} weeks ago`;\n }\n\n // Any later?\n return then.toLocaleDateString(\"en-US\", {\n timeZone: options?.timeZone,\n month: \"long\",\n day: \"numeric\",\n // omit year if it's the same as the current year\n year: now.getFullYear() !== then.getFullYear() ? \"numeric\" : undefined,\n });\n}\n\nexport function isObjectLike(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function isErrorLike(\n value: unknown,\n): value is Record<string, unknown> & { message: string } {\n return isObjectLike(value) && typeof value.message === \"string\";\n}\n\nexport function isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return typeof value === \"object\" && value !== null && \"then\" in value;\n}\n\nexport async function parseErrorResponse(\n response: Response,\n): Promise<{ message: string; status: number }> {\n try {\n const json = await response.json();\n if (!isObjectLike(json) || typeof json.message !== \"string\") {\n return {\n status: response.status,\n message: response.statusText,\n };\n }\n return {\n ...json,\n status: response.status,\n message: json.message || response.statusText,\n };\n } catch {\n return {\n status: response.status,\n message: response.statusText,\n };\n }\n}\n\nexport function namespaceClassNames(\n ...classNames: (string | undefined | null | boolean)[]\n): string {\n return classNames\n .filter(Boolean)\n .map((className) => `${WIDGETS_CLASS_NAMESPACE}-${className}`)\n .join(\" \");\n}\n\ninterface CommonDomArgs {\n className?: string | undefined | null;\n dataAttributes?: Record<string, string | boolean | undefined | null>;\n}\n\ninterface WidgetRootDomArgs {\n isWidgetRoot: true;\n widgetId: string;\n elementId?: never;\n widgetState: WidgetRootState;\n}\n\ninterface WidgetElementDomArgs {\n isWidgetRoot?: false;\n widgetId?: string;\n elementId?: keyof Elements;\n widgetState?: never;\n className: string | undefined | null;\n}\n\ntype DomArgs = CommonDomArgs & (WidgetRootDomArgs | WidgetElementDomArgs);\n\ntype DataAttributeProps = {\n [K in `data-${string}`]?: string | boolean;\n};\n\ntype DomProps = {\n className: string | undefined;\n} & DataAttributeProps;\n\nexport function getDomProps(args: DomArgs) {\n let {\n className,\n dataAttributes,\n isWidgetRoot = false,\n widgetId,\n elementId,\n widgetState,\n ...passthroughProps\n } = args;\n\n const elementClassName = elementId\n ? (() => {\n // TODO: Overrides for specific elements are mostly here for backwards\n // compatibility. They should be removed in the next major version.\n if (\n elementId === \"primaryButton\" ||\n elementId === \"secondaryButton\" ||\n elementId === \"destructiveButton\"\n ) {\n return namespaceClassNames(\"button\");\n }\n\n if (elementId === \"iconButton\") {\n return namespaceClassNames(\"button\", \"icon-button\");\n }\n\n if (\n elementId === \"primaryMenuItem\" ||\n elementId === \"destructiveMenuItem\"\n ) {\n return namespaceClassNames(\"menu-item\");\n }\n\n if (elementId === \"textfield\") {\n return namespaceClassNames(elementId, \"text-field\");\n }\n\n return namespaceClassNames(fastKebabCase(elementId));\n })()\n : undefined;\n\n const props: DomProps = {\n ...passthroughProps,\n className: cx(\n className,\n isWidgetRoot && namespaceClassNames(\"widget\"),\n elementClassName,\n ),\n };\n\n if (widgetId) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-widget-id`] = widgetId;\n }\n\n if (isWidgetRoot) {\n widgetState ??= \"resolved\";\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-widget-state`] =\n widgetState;\n }\n\n if (dataAttributes) {\n for (const [key, value] of Object.entries(dataAttributes)) {\n if (value != null) {\n const parts = [widgetId, elementId, key]\n .filter((v) => v != null)\n .map(fastKebabCase)\n .join(\"-\");\n if (parts) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-${parts}`] = value;\n }\n }\n }\n }\n\n if (elementId) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-element`] =\n fastKebabCase(elementId);\n }\n\n return props;\n}\n\n/**\n * Opt for simplicity and performance over capturing edge cases. Input strings\n * are expected to only be alphabetic.\n */\nfunction fastKebabCase(alphaString: string) {\n return alphaString.replace(/([A-Z])/g, \"-$1\").toLowerCase();\n}\n\nexport function parseUserAgent(userAgent?: string | null) {\n const browser = Bowser.getParser(userAgent ?? \"\");\n const browserName = browser.getBrowserName().replace(/^Mobile\\s*/i, \"\");\n const osName = browser.getOSName();\n const pretty = [browserName, osName].filter(Boolean).join(\" on \");\n\n return { pretty, isMobile: browser.getPlatformType() === \"mobile\" };\n}\n\nexport function getUserLocation(\n location?: {\n cityName: string;\n countryISOCode: string;\n } | null,\n ipAddress?: string | null,\n) {\n if (location) {\n return (\n [location.cityName, location.countryISOCode].filter(Boolean).join(\", \") ||\n \"Unknown location\"\n );\n }\n\n if (ipAddress) {\n return ipAddress;\n }\n\n return \"Unknown location\";\n}\n\nexport function unreachable(value: never): never {\n throw new TypeError(`Unreachable code: ${value}`);\n}\n\nexport function pluralize(word = \"\", amount = 0, showAmount = true): string {\n return `${showAmount ? `${amount} ` : \"\"}${word}${amount === 1 ? \"\" : \"s\"}`;\n}\n\n// Props that all widgets should accept.\nexport interface WidgetRootDomProps {\n className?: string;\n}\n\nexport type WidgetRootState = \"loading\" | \"error\" | \"resolved\";\n"],"mappings":"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","names":["cx","Bowser"]}
1
+ {"version":3,"sources":["../../../src/lib/utils.ts"],"sourcesContent":["import { Member } from \"../api/endpoint.js\";\nimport Bowser from \"bowser\";\nimport cx from \"clsx\";\nimport {\n WIDGETS_CLASS_NAMESPACE,\n WIDGETS_DATA_ATTRIBUTE_NAMESPACE,\n} from \"./constants.js\";\nimport type { Elements } from \"./elements.js\";\n\nexport const canUseDOM = !!(\n typeof window !== \"undefined\" &&\n window.document &&\n window.document.createElement\n);\n\nexport function getBestName({\n firstName,\n lastName,\n}: Pick<Member, \"firstName\" | \"lastName\">) {\n return [firstName, lastName].filter(Boolean).join(\" \") || null;\n}\n\nexport function getComparativeReadableDate(\n now: Date,\n then: Date,\n options?: { timeZone?: string },\n): string {\n const timeSince = now.getTime() - then.getTime();\n\n // Has it been less than a minute?\n if (timeSince < 60_000) {\n return \"Just now\";\n }\n\n // Has it been less than an hour?\n if (timeSince < 3_600_000) {\n const timePassed = Math.floor(timeSince / 60_000);\n return timePassed === 1 ? \"1 minute ago\" : `${timePassed} minutes ago`;\n }\n\n // Has it been less than a day?\n if (timeSince < 86_400_000) {\n const timePassed = Math.floor(timeSince / 3_600_000);\n return timePassed === 1 ? \"1 hour ago\" : `${timePassed} hours ago`;\n }\n\n // Has it been less than a week?\n if (timeSince < 604_800_000) {\n const timePassed = Math.floor(timeSince / 86_400_000);\n return timePassed === 1 ? \"1 day ago\" : `${timePassed} days ago`;\n }\n\n // Has it been less than a month?\n if (timeSince < 2_592_000_000) {\n const timePassed = Math.floor(timeSince / 604_800_000);\n return timePassed === 1 ? \"1 week ago\" : `${timePassed} weeks ago`;\n }\n\n // Any later?\n return then.toLocaleDateString(\"en-US\", {\n timeZone: options?.timeZone,\n month: \"long\",\n day: \"numeric\",\n // omit year if it's the same as the current year\n year: now.getFullYear() !== then.getFullYear() ? \"numeric\" : undefined,\n });\n}\n\nexport function isObjectLike(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function isErrorLike(\n value: unknown,\n): value is Record<string, unknown> & { message: string } {\n return isObjectLike(value) && typeof value.message === \"string\";\n}\n\nexport function isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"then\" in value &&\n typeof value.then === \"function\"\n );\n}\n\nexport async function parseErrorResponse(\n response: Response,\n): Promise<{ message: string; status: number }> {\n try {\n const json = await response.json();\n if (!isObjectLike(json) || typeof json.message !== \"string\") {\n return {\n status: response.status,\n message: response.statusText,\n };\n }\n return {\n ...json,\n status: response.status,\n message: json.message || response.statusText,\n };\n } catch {\n return {\n status: response.status,\n message: response.statusText,\n };\n }\n}\n\nexport function namespaceClassNames(\n ...classNames: (string | undefined | null | boolean)[]\n): string {\n return classNames\n .filter(Boolean)\n .map((className) => `${WIDGETS_CLASS_NAMESPACE}-${className}`)\n .join(\" \");\n}\n\ninterface CommonDomArgs {\n className?: string | undefined | null;\n dataAttributes?: Record<string, string | boolean | undefined | null>;\n}\n\ninterface WidgetRootDomArgs {\n isWidgetRoot: true;\n widgetId: string;\n elementId?: never;\n widgetState: WidgetRootState;\n}\n\ninterface WidgetElementDomArgs {\n isWidgetRoot?: false;\n widgetId?: string;\n elementId?: keyof Elements;\n widgetState?: never;\n className: string | undefined | null;\n}\n\ntype DomArgs = CommonDomArgs & (WidgetRootDomArgs | WidgetElementDomArgs);\n\ntype DataAttributeProps = {\n [K in `data-${string}`]?: string | boolean;\n};\n\ntype DomProps = {\n className: string | undefined;\n} & DataAttributeProps;\n\nexport function getDomProps(args: DomArgs) {\n let {\n className,\n dataAttributes,\n isWidgetRoot = false,\n widgetId,\n elementId,\n widgetState,\n ...passthroughProps\n } = args;\n\n const elementClassName = elementId\n ? (() => {\n // TODO: Overrides for specific elements are mostly here for backwards\n // compatibility. They should be removed in the next major version.\n if (\n elementId === \"primaryButton\" ||\n elementId === \"secondaryButton\" ||\n elementId === \"destructiveButton\"\n ) {\n return namespaceClassNames(\"button\");\n }\n\n if (elementId === \"iconButton\") {\n return namespaceClassNames(\"button\", \"icon-button\");\n }\n\n if (\n elementId === \"primaryMenuItem\" ||\n elementId === \"destructiveMenuItem\"\n ) {\n return namespaceClassNames(\"menu-item\");\n }\n\n if (elementId === \"textfield\") {\n return namespaceClassNames(elementId, \"text-field\");\n }\n\n return namespaceClassNames(fastKebabCase(elementId));\n })()\n : undefined;\n\n const props: DomProps = {\n ...passthroughProps,\n className: cx(\n className,\n isWidgetRoot && namespaceClassNames(\"widget\"),\n elementClassName,\n ),\n };\n\n if (widgetId) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-widget-id`] = widgetId;\n }\n\n if (isWidgetRoot) {\n widgetState ??= \"resolved\";\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-widget-state`] =\n widgetState;\n }\n\n if (dataAttributes) {\n for (const [key, value] of Object.entries(dataAttributes)) {\n if (value != null) {\n const parts = [widgetId, elementId, key]\n .filter((v) => v != null)\n .map(fastKebabCase)\n .join(\"-\");\n if (parts) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-${parts}`] = value;\n }\n }\n }\n }\n\n if (elementId) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-element`] =\n fastKebabCase(elementId);\n }\n\n return props;\n}\n\n/**\n * Opt for simplicity and performance over capturing edge cases. Input strings\n * are expected to only be alphabetic.\n */\nfunction fastKebabCase(alphaString: string) {\n return alphaString.replace(/([A-Z])/g, \"-$1\").toLowerCase();\n}\n\nexport function parseUserAgent(userAgent?: string | null) {\n const browser = Bowser.getParser(userAgent ?? \"\");\n const browserName = browser.getBrowserName().replace(/^Mobile\\s*/i, \"\");\n const osName = browser.getOSName();\n const pretty = [browserName, osName].filter(Boolean).join(\" on \");\n\n return { pretty, isMobile: browser.getPlatformType() === \"mobile\" };\n}\n\nexport function getUserLocation(\n location?: {\n cityName: string;\n countryISOCode: string;\n } | null,\n ipAddress?: string | null,\n) {\n if (location) {\n return (\n [location.cityName, location.countryISOCode].filter(Boolean).join(\", \") ||\n \"Unknown location\"\n );\n }\n\n if (ipAddress) {\n return ipAddress;\n }\n\n return \"Unknown location\";\n}\n\nexport function unreachable(value: never): never {\n throw new TypeError(`Unreachable code: ${value}`);\n}\n\nexport function pluralize(word = \"\", amount = 0, showAmount = true): string {\n return `${showAmount ? `${amount} ` : \"\"}${word}${amount === 1 ? \"\" : \"s\"}`;\n}\n\n// Props that all widgets should accept.\nexport interface WidgetRootDomProps {\n className?: string;\n}\n\nexport type WidgetRootState = \"loading\" | \"error\" | \"resolved\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,oBAAmB;AACnB,kBAAe;AACf,uBAGO;AAGA,MAAM,YAAY,CAAC,EACxB,OAAO,WAAW,eAClB,OAAO,YACP,OAAO,SAAS;AAGX,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AACF,GAA2C;AACzC,SAAO,CAAC,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,KAAK;AAC5D;AAEO,SAAS,2BACd,KACA,MACA,SACQ;AACR,QAAM,YAAY,IAAI,QAAQ,IAAI,KAAK,QAAQ;AAG/C,MAAI,YAAY,KAAQ;AACtB,WAAO;AAAA,EACT;AAGA,MAAI,YAAY,MAAW;AACzB,UAAM,aAAa,KAAK,MAAM,YAAY,GAAM;AAChD,WAAO,eAAe,IAAI,iBAAiB,GAAG,UAAU;AAAA,EAC1D;AAGA,MAAI,YAAY,OAAY;AAC1B,UAAM,aAAa,KAAK,MAAM,YAAY,IAAS;AACnD,WAAO,eAAe,IAAI,eAAe,GAAG,UAAU;AAAA,EACxD;AAGA,MAAI,YAAY,QAAa;AAC3B,UAAM,aAAa,KAAK,MAAM,YAAY,KAAU;AACpD,WAAO,eAAe,IAAI,cAAc,GAAG,UAAU;AAAA,EACvD;AAGA,MAAI,YAAY,QAAe;AAC7B,UAAM,aAAa,KAAK,MAAM,YAAY,MAAW;AACrD,WAAO,eAAe,IAAI,eAAe,GAAG,UAAU;AAAA,EACxD;AAGA,SAAO,KAAK,mBAAmB,SAAS;AAAA,IACtC,UAAU,SAAS;AAAA,IACnB,OAAO;AAAA,IACP,KAAK;AAAA;AAAA,IAEL,MAAM,IAAI,YAAY,MAAM,KAAK,YAAY,IAAI,YAAY;AAAA,EAC/D,CAAC;AACH;AAEO,SAAS,aAAa,OAAkD;AAC7E,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEO,SAAS,YACd,OACwD;AACxD,SAAO,aAAa,KAAK,KAAK,OAAO,MAAM,YAAY;AACzD;AAEO,SAAS,cAAc,OAA+C;AAC3E,SACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAO,MAAM,SAAS;AAE1B;AAEA,eAAsB,mBACpB,UAC8C;AAC9C,MAAI;AACF,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI,CAAC,aAAa,IAAI,KAAK,OAAO,KAAK,YAAY,UAAU;AAC3D,aAAO;AAAA,QACL,QAAQ,SAAS;AAAA,QACjB,SAAS,SAAS;AAAA,MACpB;AAAA,IACF;AACA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ,SAAS;AAAA,MACjB,SAAS,KAAK,WAAW,SAAS;AAAA,IACpC;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,MACL,QAAQ,SAAS;AAAA,MACjB,SAAS,SAAS;AAAA,IACpB;AAAA,EACF;AACF;AAEO,SAAS,uBACX,YACK;AACR,SAAO,WACJ,OAAO,OAAO,EACd,IAAI,CAAC,cAAc,GAAG,wCAAuB,IAAI,SAAS,EAAE,EAC5D,KAAK,GAAG;AACb;AAgCO,SAAS,YAAY,MAAe;AACzC,MAAI;AAAA,IACF;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,mBAAmB,aACpB,MAAM;AAGL,QACE,cAAc,mBACd,cAAc,qBACd,cAAc,qBACd;AACA,aAAO,oBAAoB,QAAQ;AAAA,IACrC;AAEA,QAAI,cAAc,cAAc;AAC9B,aAAO,oBAAoB,UAAU,aAAa;AAAA,IACpD;AAEA,QACE,cAAc,qBACd,cAAc,uBACd;AACA,aAAO,oBAAoB,WAAW;AAAA,IACxC;AAEA,QAAI,cAAc,aAAa;AAC7B,aAAO,oBAAoB,WAAW,YAAY;AAAA,IACpD;AAEA,WAAO,oBAAoB,cAAc,SAAS,CAAC;AAAA,EACrD,GAAG,IACH;AAEJ,QAAM,QAAkB;AAAA,IACtB,GAAG;AAAA,IACH,eAAW,YAAAA;AAAA,MACT;AAAA,MACA,gBAAgB,oBAAoB,QAAQ;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU;AACZ,UAAM,QAAQ,iDAAgC,YAAY,IAAI;AAAA,EAChE;AAEA,MAAI,cAAc;AAChB,oBAAgB;AAChB,UAAM,QAAQ,iDAAgC,eAAe,IAC3D;AAAA,EACJ;AAEA,MAAI,gBAAgB;AAClB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,cAAc,GAAG;AACzD,UAAI,SAAS,MAAM;AACjB,cAAM,QAAQ,CAAC,UAAU,WAAW,GAAG,EACpC,OAAO,CAAC,MAAM,KAAK,IAAI,EACvB,IAAI,aAAa,EACjB,KAAK,GAAG;AACX,YAAI,OAAO;AACT,gBAAM,QAAQ,iDAAgC,IAAI,KAAK,EAAE,IAAI;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,WAAW;AACb,UAAM,QAAQ,iDAAgC,UAAU,IACtD,cAAc,SAAS;AAAA,EAC3B;AAEA,SAAO;AACT;AAMA,SAAS,cAAc,aAAqB;AAC1C,SAAO,YAAY,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC5D;AAEO,SAAS,eAAe,WAA2B;AACxD,QAAM,UAAU,cAAAC,QAAO,UAAU,aAAa,EAAE;AAChD,QAAM,cAAc,QAAQ,eAAe,EAAE,QAAQ,eAAe,EAAE;AACtE,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,SAAS,CAAC,aAAa,MAAM,EAAE,OAAO,OAAO,EAAE,KAAK,MAAM;AAEhE,SAAO,EAAE,QAAQ,UAAU,QAAQ,gBAAgB,MAAM,SAAS;AACpE;AAEO,SAAS,gBACd,UAIA,WACA;AACA,MAAI,UAAU;AACZ,WACE,CAAC,SAAS,UAAU,SAAS,cAAc,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,KACtE;AAAA,EAEJ;AAEA,MAAI,WAAW;AACb,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,YAAY,OAAqB;AAC/C,QAAM,IAAI,UAAU,qBAAqB,KAAK,EAAE;AAClD;AAEO,SAAS,UAAU,OAAO,IAAI,SAAS,GAAG,aAAa,MAAc;AAC1E,SAAO,GAAG,aAAa,GAAG,MAAM,MAAM,EAAE,GAAG,IAAI,GAAG,WAAW,IAAI,KAAK,GAAG;AAC3E;","names":["cx","Bowser"]}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var utils_exports = {};
30
+ __export(utils_exports, {
31
+ unstable_useWidgetsInvalidator: () => useWidgetsInvalidator
32
+ });
33
+ module.exports = __toCommonJS(utils_exports);
34
+ var React = __toESM(require("react"), 1);
35
+ var import_react_query = require("@tanstack/react-query");
36
+ function useWidgetsInvalidator() {
37
+ let queryClient;
38
+ try {
39
+ queryClient = (0, import_react_query.useQueryClient)();
40
+ } catch {
41
+ throw Error(
42
+ "useWidgetsInvalidation must be used within the `WorkOsWidgets` provider component"
43
+ );
44
+ }
45
+ return React.useCallback(async () => {
46
+ await queryClient.invalidateQueries({ queryKey: ["authToken"] });
47
+ await new Promise((resolve) => setTimeout(resolve, 1));
48
+ return queryClient.invalidateQueries({
49
+ predicate: (query) => query.queryKey.some(
50
+ (key) => typeof key === "string" && key.startsWith("/_widgets/")
51
+ )
52
+ });
53
+ }, [queryClient]);
54
+ }
55
+ // Annotate the CommonJS export names for ESM import in node:
56
+ 0 && (module.exports = {
57
+ unstable_useWidgetsInvalidator
58
+ });
59
+ //# sourceMappingURL=utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils.ts"],"sourcesContent":["import * as React from \"react\";\nimport { useQueryClient, type QueryClient } from \"@tanstack/react-query\";\n\nfunction useWidgetsInvalidator() {\n let queryClient: QueryClient;\n try {\n queryClient = useQueryClient();\n } catch {\n throw Error(\n \"useWidgetsInvalidation must be used within the `WorkOsWidgets` provider component\",\n );\n }\n\n return React.useCallback(async () => {\n await queryClient.invalidateQueries({ queryKey: [\"authToken\"] });\n // TODO: Unclear why, but invalidating other widgets' queries immediately\n // after the authToken invalidation (even though it's async?) doesn't work,\n // and We end up with stale data. Waiting for the next tick fixes this.\n await new Promise((resolve) => setTimeout(resolve, 1));\n return queryClient.invalidateQueries({\n predicate: (query) =>\n query.queryKey.some(\n (key) => typeof key === \"string\" && key.startsWith(\"/_widgets/\"),\n ),\n });\n }, [queryClient]);\n}\n\nexport { useWidgetsInvalidator as unstable_useWidgetsInvalidator };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAuB;AACvB,yBAAiD;AAEjD,SAAS,wBAAwB;AAC/B,MAAI;AACJ,MAAI;AACF,sBAAc,mCAAe;AAAA,EAC/B,QAAQ;AACN,UAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAEA,SAAO,MAAM,YAAY,YAAY;AACnC,UAAM,YAAY,kBAAkB,EAAE,UAAU,CAAC,WAAW,EAAE,CAAC;AAI/D,UAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,CAAC,CAAC;AACrD,WAAO,YAAY,kBAAkB;AAAA,MACnC,WAAW,CAAC,UACV,MAAM,SAAS;AAAA,QACb,CAAC,QAAQ,OAAO,QAAQ,YAAY,IAAI,WAAW,YAAY;AAAA,MACjE;AAAA,IACJ,CAAC;AAAA,EACH,GAAG,CAAC,WAAW,CAAC;AAClB;","names":[]}
@@ -0,0 +1,3 @@
1
+ declare function useWidgetsInvalidator(): () => Promise<void>;
2
+
3
+ export { useWidgetsInvalidator as unstable_useWidgetsInvalidator };
@@ -19,7 +19,7 @@ import {
19
19
  Skeleton,
20
20
  DropdownMenu
21
21
  } from "./elements.js";
22
- import { useQueryClient } from "@tanstack/react-query";
22
+ import { unstable_useWidgetsInvalidator as useWidgetsInvalidator } from "../utils.js";
23
23
  const OrganizationSwitcher = ({
24
24
  organizations,
25
25
  switchToOrganization,
@@ -32,8 +32,7 @@ const OrganizationSwitcher = ({
32
32
  const currentOrganization = organizations.find(
33
33
  (organization) => organization.current
34
34
  );
35
- const queryClient = useQueryClient();
36
- const invalidateAllWidgets = () => queryClient.invalidateQueries({ queryKey: ["/_widgets/"] });
35
+ const invalidateAllWidgets = useWidgetsInvalidator();
37
36
  if (!currentOrganization) {
38
37
  return null;
39
38
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/organization-switcher.tsx"],"sourcesContent":["\"use client\";\n\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport {\n Box,\n ChevronDownIcon,\n Flex,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport type { OrganizationInfo } from \"../api/endpoint.js\";\nimport cx from \"clsx\";\nimport {\n getDomProps,\n isPromiseLike,\n type WidgetRootDomProps,\n type WidgetRootState,\n} from \"./utils.js\";\nimport { getErrorMessage } from \"./generic-error.js\";\nimport {\n Button,\n type ButtonProps,\n Skeleton,\n DropdownMenu,\n} from \"./elements.js\";\nimport { useQueryClient } from \"@tanstack/react-query\";\n\ntype OrganizationSwitcherVariant = \"ghost\" | \"outline\";\n\n// Rename all uses of `org` to `organization`\ninterface OrganizationSwitcherPassthroughProps extends WidgetRootDomProps {\n switchToOrganization: ({\n organizationId,\n }: {\n organizationId: string;\n }) => void | Promise<void>;\n // Simple props to affect the overall style\n variant?: OrganizationSwitcherVariant;\n organizationLabel?: string | null;\n children?: React.ReactNode;\n /**\n * Choose where to truncate organization name in the trigger and dropdown\n * items.\n *\n * - `right`: Truncate the right side of the organization name\n * - `middle`: Truncate the middle of the organization name, trying to keep\n * words whole\n */\n truncateBehavior?: \"right\" | \"middle\";\n}\n\ninterface OrganizationSwitcherProps\n extends OrganizationSwitcherPassthroughProps {\n organizations: OrganizationInfo[];\n}\n\nconst OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({\n organizations,\n switchToOrganization,\n variant,\n organizationLabel = \"Organizations\",\n truncateBehavior = \"right\",\n children,\n ...domProps\n}) => {\n const currentOrganization = organizations.find(\n (organization) => organization.current,\n );\n const queryClient = useQueryClient();\n const invalidateAllWidgets = () =>\n queryClient.invalidateQueries({ queryKey: [\"/_widgets/\"] });\n\n // TODO: Possible if the user has no organizations - we should figure out what\n // to do in this case\n if (!currentOrganization) {\n return null;\n }\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <Button\n variant=\"secondary\"\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"resolved\", {\n ...domProps,\n // TODO: Remove `OrganizationSwitcherTrigger` in the next major\n // version. This should follow conventions of all other widgets\n // using classnames in getWidgetRootDomProps.\n className: cx(domProps.className, \"OrganizationSwitcherTrigger\"),\n })}\n >\n <Flex\n align=\"center\"\n justify=\"between\"\n gap=\"2\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n minWidth=\"0\"\n >\n <TruncatedOrganizationName\n organizationName={currentOrganization.name}\n truncateBehavior={truncateBehavior}\n />\n <Flex asChild flexShrink=\"0\">\n <DropdownMenu.TriggerIcon />\n </Flex>\n </Flex>\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Group>\n {organizationLabel ? (\n <DropdownMenu.Label>\n <Text>{organizationLabel}</Text>\n </DropdownMenu.Label>\n ) : null}\n {organizations.map((organization) => (\n <Flex\n key={organization.id}\n asChild\n pr=\"2\"\n maxWidth=\"280px\"\n minWidth=\"180px\"\n >\n <DropdownMenu.Item\n onClick={() => {\n if (organization.id !== currentOrganization.id) {\n const result = switchToOrganization({\n organizationId: organization.id,\n });\n if (isPromiseLike(result)) {\n result.then(invalidateAllWidgets);\n } else {\n invalidateAllWidgets();\n }\n }\n }}\n >\n <Flex\n justify=\"between\"\n align=\"center\"\n gap=\"4\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n >\n <TruncatedOrganizationName\n organizationName={organization.name}\n truncateBehavior={truncateBehavior}\n />\n {organization.current && (\n <VisuallyHidden> (current)</VisuallyHidden>\n )}\n <Flex\n aria-hidden\n align=\"center\"\n justify=\"center\"\n flexShrink=\"0\"\n >\n {organization.current ? (\n <CheckIcon width=\"18px\" height=\"18px\" />\n ) : (\n // make the extra space for\n <Box width=\"18px\" height=\"18px\" />\n )}\n </Flex>\n </Flex>\n </DropdownMenu.Item>\n </Flex>\n ))}\n </DropdownMenu.Group>\n {children}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n};\n\ninterface OrganizationSwitcherLoadingProps extends WidgetRootDomProps {\n variant?: OrganizationSwitcherVariant;\n}\n\nconst OrganizationSwitcherLoading: React.FC<\n OrganizationSwitcherLoadingProps\n> = ({ variant, ...props }: OrganizationSwitcherLoadingProps) => {\n return (\n // Always need DropdownMenu.Root to wrap children than may include\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"loading\", props)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Skeleton>\n <Text>Loading...</Text>\n </Skeleton>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n};\n\ninterface OrganizationSwitcherErrorProps extends WidgetRootDomProps {\n error: unknown;\n variant?: OrganizationSwitcherVariant;\n}\n\nfunction OrganizationSwitcherError({\n error,\n variant,\n ...domProps\n}: OrganizationSwitcherErrorProps) {\n const { heading } = getErrorMessage(error);\n\n return (\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"error\", domProps)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Text>{heading}</Text>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n}\n\nconst MAX_TRUNCATED_SUFFIX_LENGTH = 10;\nconst MIN_TRUNCATED_SUFFIX_LENGTH = 3;\n\nconst WHITE_SPACE_REGEX = /\\s/;\n\nconst getSplitPosition = (organizationName: string) => {\n if (organizationName.length <= MAX_TRUNCATED_SUFFIX_LENGTH) {\n return organizationName.length;\n }\n\n for (\n let i = organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n i < organizationName.length - MIN_TRUNCATED_SUFFIX_LENGTH;\n i++\n ) {\n if (WHITE_SPACE_REGEX.test(organizationName[i - 1])) {\n return i;\n }\n }\n\n return organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n};\n\nconst splitOrganizationName = (organizationName: string) => {\n const splitPosition = getSplitPosition(organizationName);\n return [\n organizationName.slice(0, splitPosition),\n organizationName.slice(splitPosition),\n ];\n};\n\nconst TruncatedOrganizationName = ({\n organizationName,\n truncateBehavior,\n}: {\n organizationName: string;\n truncateBehavior: \"right\" | \"middle\";\n}) => {\n if (truncateBehavior === \"right\") {\n return <Text truncate>{organizationName}</Text>;\n }\n\n const [organizationNameLeft, organizationNameRight] =\n splitOrganizationName(organizationName);\n\n return (\n <Flex overflow=\"hidden\">\n <VisuallyHidden>\n <Text>{organizationName}</Text>\n </VisuallyHidden>\n <Text aria-hidden truncate style={{ whiteSpace: \"pre\" }}>\n {organizationNameLeft}\n </Text>\n <Text aria-hidden>{organizationNameRight}</Text>\n </Flex>\n );\n};\n\nfunction mapVariantProps(variant?: OrganizationSwitcherVariant): ButtonProps {\n const variantProps: ButtonProps = {};\n // Passing `undefined` to the variant prop will result in overrides to props we\n // set internally. This should be addressed in Radix Themes, but we can\n // explicitly set it only when it's provided and _not_ undefined.\n if (variant) {\n variantProps.unsafe_radixVariant = variant;\n }\n return variantProps;\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"organization-switcher\",\n widgetState: state,\n });\n}\n\nexport type {\n OrganizationSwitcherProps,\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherErrorProps,\n /** @internal */\n OrganizationSwitcherPassthroughProps,\n};\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n OrganizationSwitcherError,\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/organization-switcher.tsx"],"sourcesContent":["\"use client\";\n\nimport { CheckIcon } from \"@radix-ui/react-icons\";\nimport {\n Box,\n ChevronDownIcon,\n Flex,\n Text,\n VisuallyHidden,\n} from \"@radix-ui/themes\";\nimport type { OrganizationInfo } from \"../api/endpoint.js\";\nimport cx from \"clsx\";\nimport {\n getDomProps,\n isPromiseLike,\n type WidgetRootDomProps,\n type WidgetRootState,\n} from \"./utils.js\";\nimport { getErrorMessage } from \"./generic-error.js\";\nimport {\n Button,\n type ButtonProps,\n Skeleton,\n DropdownMenu,\n} from \"./elements.js\";\nimport { unstable_useWidgetsInvalidator as useWidgetsInvalidator } from \"../utils.js\";\n\ntype OrganizationSwitcherVariant = \"ghost\" | \"outline\";\n\n// Rename all uses of `org` to `organization`\ninterface OrganizationSwitcherPassthroughProps extends WidgetRootDomProps {\n switchToOrganization: ({\n organizationId,\n }: {\n organizationId: string;\n }) => void | Promise<void>;\n // Simple props to affect the overall style\n variant?: OrganizationSwitcherVariant;\n organizationLabel?: string | null;\n children?: React.ReactNode;\n /**\n * Choose where to truncate organization name in the trigger and dropdown\n * items.\n *\n * - `right`: Truncate the right side of the organization name\n * - `middle`: Truncate the middle of the organization name, trying to keep\n * words whole\n */\n truncateBehavior?: \"right\" | \"middle\";\n}\n\ninterface OrganizationSwitcherProps\n extends OrganizationSwitcherPassthroughProps {\n organizations: OrganizationInfo[];\n}\n\nconst OrganizationSwitcher: React.FC<OrganizationSwitcherProps> = ({\n organizations,\n switchToOrganization,\n variant,\n organizationLabel = \"Organizations\",\n truncateBehavior = \"right\",\n children,\n ...domProps\n}) => {\n const currentOrganization = organizations.find(\n (organization) => organization.current,\n );\n const invalidateAllWidgets = useWidgetsInvalidator();\n\n // TODO: Possible if the user has no organizations - we should figure out what\n // to do in this case\n if (!currentOrganization) {\n return null;\n }\n\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <Button\n variant=\"secondary\"\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"resolved\", {\n ...domProps,\n // TODO: Remove `OrganizationSwitcherTrigger` in the next major\n // version. This should follow conventions of all other widgets\n // using classnames in getWidgetRootDomProps.\n className: cx(domProps.className, \"OrganizationSwitcherTrigger\"),\n })}\n >\n <Flex\n align=\"center\"\n justify=\"between\"\n gap=\"2\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n minWidth=\"0\"\n >\n <TruncatedOrganizationName\n organizationName={currentOrganization.name}\n truncateBehavior={truncateBehavior}\n />\n <Flex asChild flexShrink=\"0\">\n <DropdownMenu.TriggerIcon />\n </Flex>\n </Flex>\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Group>\n {organizationLabel ? (\n <DropdownMenu.Label>\n <Text>{organizationLabel}</Text>\n </DropdownMenu.Label>\n ) : null}\n {organizations.map((organization) => (\n <Flex\n key={organization.id}\n asChild\n pr=\"2\"\n maxWidth=\"280px\"\n minWidth=\"180px\"\n >\n <DropdownMenu.Item\n onClick={() => {\n if (organization.id !== currentOrganization.id) {\n const result = switchToOrganization({\n organizationId: organization.id,\n });\n if (isPromiseLike(result)) {\n result.then(invalidateAllWidgets);\n } else {\n invalidateAllWidgets();\n }\n }\n }}\n >\n <Flex\n justify=\"between\"\n align=\"center\"\n gap=\"4\"\n flexGrow=\"1\"\n overflow=\"hidden\"\n >\n <TruncatedOrganizationName\n organizationName={organization.name}\n truncateBehavior={truncateBehavior}\n />\n {organization.current && (\n <VisuallyHidden> (current)</VisuallyHidden>\n )}\n <Flex\n aria-hidden\n align=\"center\"\n justify=\"center\"\n flexShrink=\"0\"\n >\n {organization.current ? (\n <CheckIcon width=\"18px\" height=\"18px\" />\n ) : (\n // make the extra space for\n <Box width=\"18px\" height=\"18px\" />\n )}\n </Flex>\n </Flex>\n </DropdownMenu.Item>\n </Flex>\n ))}\n </DropdownMenu.Group>\n {children}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n};\n\ninterface OrganizationSwitcherLoadingProps extends WidgetRootDomProps {\n variant?: OrganizationSwitcherVariant;\n}\n\nconst OrganizationSwitcherLoading: React.FC<\n OrganizationSwitcherLoadingProps\n> = ({ variant, ...props }: OrganizationSwitcherLoadingProps) => {\n return (\n // Always need DropdownMenu.Root to wrap children than may include\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"loading\", props)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Skeleton>\n <Text>Loading...</Text>\n </Skeleton>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n};\n\ninterface OrganizationSwitcherErrorProps extends WidgetRootDomProps {\n error: unknown;\n variant?: OrganizationSwitcherVariant;\n}\n\nfunction OrganizationSwitcherError({\n error,\n variant,\n ...domProps\n}: OrganizationSwitcherErrorProps) {\n const { heading } = getErrorMessage(error);\n\n return (\n <Button\n variant=\"secondary\"\n disabled\n {...mapVariantProps(variant)}\n {...getWidgetRootDomProps(\"error\", domProps)}\n >\n <Flex align=\"center\" gap=\"2\">\n <Text>{heading}</Text>\n <ChevronDownIcon />\n </Flex>\n </Button>\n );\n}\n\nconst MAX_TRUNCATED_SUFFIX_LENGTH = 10;\nconst MIN_TRUNCATED_SUFFIX_LENGTH = 3;\n\nconst WHITE_SPACE_REGEX = /\\s/;\n\nconst getSplitPosition = (organizationName: string) => {\n if (organizationName.length <= MAX_TRUNCATED_SUFFIX_LENGTH) {\n return organizationName.length;\n }\n\n for (\n let i = organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n i < organizationName.length - MIN_TRUNCATED_SUFFIX_LENGTH;\n i++\n ) {\n if (WHITE_SPACE_REGEX.test(organizationName[i - 1])) {\n return i;\n }\n }\n\n return organizationName.length - MAX_TRUNCATED_SUFFIX_LENGTH;\n};\n\nconst splitOrganizationName = (organizationName: string) => {\n const splitPosition = getSplitPosition(organizationName);\n return [\n organizationName.slice(0, splitPosition),\n organizationName.slice(splitPosition),\n ];\n};\n\nconst TruncatedOrganizationName = ({\n organizationName,\n truncateBehavior,\n}: {\n organizationName: string;\n truncateBehavior: \"right\" | \"middle\";\n}) => {\n if (truncateBehavior === \"right\") {\n return <Text truncate>{organizationName}</Text>;\n }\n\n const [organizationNameLeft, organizationNameRight] =\n splitOrganizationName(organizationName);\n\n return (\n <Flex overflow=\"hidden\">\n <VisuallyHidden>\n <Text>{organizationName}</Text>\n </VisuallyHidden>\n <Text aria-hidden truncate style={{ whiteSpace: \"pre\" }}>\n {organizationNameLeft}\n </Text>\n <Text aria-hidden>{organizationNameRight}</Text>\n </Flex>\n );\n};\n\nfunction mapVariantProps(variant?: OrganizationSwitcherVariant): ButtonProps {\n const variantProps: ButtonProps = {};\n // Passing `undefined` to the variant prop will result in overrides to props we\n // set internally. This should be addressed in Radix Themes, but we can\n // explicitly set it only when it's provided and _not_ undefined.\n if (variant) {\n variantProps.unsafe_radixVariant = variant;\n }\n return variantProps;\n}\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"organization-switcher\",\n widgetState: state,\n });\n}\n\nexport type {\n OrganizationSwitcherProps,\n OrganizationSwitcherLoadingProps,\n OrganizationSwitcherErrorProps,\n /** @internal */\n OrganizationSwitcherPassthroughProps,\n};\nexport {\n OrganizationSwitcher,\n OrganizationSwitcherLoading,\n OrganizationSwitcherError,\n};\n"],"mappings":"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","names":[]}
@@ -47,7 +47,7 @@ function isErrorLike(value) {
47
47
  return isObjectLike(value) && typeof value.message === "string";
48
48
  }
49
49
  function isPromiseLike(value) {
50
- return typeof value === "object" && value !== null && "then" in value;
50
+ return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
51
51
  }
52
52
  async function parseErrorResponse(response) {
53
53
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils.ts"],"sourcesContent":["import { Member } from \"../api/endpoint.js\";\nimport Bowser from \"bowser\";\nimport cx from \"clsx\";\nimport {\n WIDGETS_CLASS_NAMESPACE,\n WIDGETS_DATA_ATTRIBUTE_NAMESPACE,\n} from \"./constants.js\";\nimport type { Elements } from \"./elements.js\";\n\nexport const canUseDOM = !!(\n typeof window !== \"undefined\" &&\n window.document &&\n window.document.createElement\n);\n\nexport function getBestName({\n firstName,\n lastName,\n}: Pick<Member, \"firstName\" | \"lastName\">) {\n return [firstName, lastName].filter(Boolean).join(\" \") || null;\n}\n\nexport function getComparativeReadableDate(\n now: Date,\n then: Date,\n options?: { timeZone?: string },\n): string {\n const timeSince = now.getTime() - then.getTime();\n\n // Has it been less than a minute?\n if (timeSince < 60_000) {\n return \"Just now\";\n }\n\n // Has it been less than an hour?\n if (timeSince < 3_600_000) {\n const timePassed = Math.floor(timeSince / 60_000);\n return timePassed === 1 ? \"1 minute ago\" : `${timePassed} minutes ago`;\n }\n\n // Has it been less than a day?\n if (timeSince < 86_400_000) {\n const timePassed = Math.floor(timeSince / 3_600_000);\n return timePassed === 1 ? \"1 hour ago\" : `${timePassed} hours ago`;\n }\n\n // Has it been less than a week?\n if (timeSince < 604_800_000) {\n const timePassed = Math.floor(timeSince / 86_400_000);\n return timePassed === 1 ? \"1 day ago\" : `${timePassed} days ago`;\n }\n\n // Has it been less than a month?\n if (timeSince < 2_592_000_000) {\n const timePassed = Math.floor(timeSince / 604_800_000);\n return timePassed === 1 ? \"1 week ago\" : `${timePassed} weeks ago`;\n }\n\n // Any later?\n return then.toLocaleDateString(\"en-US\", {\n timeZone: options?.timeZone,\n month: \"long\",\n day: \"numeric\",\n // omit year if it's the same as the current year\n year: now.getFullYear() !== then.getFullYear() ? \"numeric\" : undefined,\n });\n}\n\nexport function isObjectLike(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function isErrorLike(\n value: unknown,\n): value is Record<string, unknown> & { message: string } {\n return isObjectLike(value) && typeof value.message === \"string\";\n}\n\nexport function isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return typeof value === \"object\" && value !== null && \"then\" in value;\n}\n\nexport async function parseErrorResponse(\n response: Response,\n): Promise<{ message: string; status: number }> {\n try {\n const json = await response.json();\n if (!isObjectLike(json) || typeof json.message !== \"string\") {\n return {\n status: response.status,\n message: response.statusText,\n };\n }\n return {\n ...json,\n status: response.status,\n message: json.message || response.statusText,\n };\n } catch {\n return {\n status: response.status,\n message: response.statusText,\n };\n }\n}\n\nexport function namespaceClassNames(\n ...classNames: (string | undefined | null | boolean)[]\n): string {\n return classNames\n .filter(Boolean)\n .map((className) => `${WIDGETS_CLASS_NAMESPACE}-${className}`)\n .join(\" \");\n}\n\ninterface CommonDomArgs {\n className?: string | undefined | null;\n dataAttributes?: Record<string, string | boolean | undefined | null>;\n}\n\ninterface WidgetRootDomArgs {\n isWidgetRoot: true;\n widgetId: string;\n elementId?: never;\n widgetState: WidgetRootState;\n}\n\ninterface WidgetElementDomArgs {\n isWidgetRoot?: false;\n widgetId?: string;\n elementId?: keyof Elements;\n widgetState?: never;\n className: string | undefined | null;\n}\n\ntype DomArgs = CommonDomArgs & (WidgetRootDomArgs | WidgetElementDomArgs);\n\ntype DataAttributeProps = {\n [K in `data-${string}`]?: string | boolean;\n};\n\ntype DomProps = {\n className: string | undefined;\n} & DataAttributeProps;\n\nexport function getDomProps(args: DomArgs) {\n let {\n className,\n dataAttributes,\n isWidgetRoot = false,\n widgetId,\n elementId,\n widgetState,\n ...passthroughProps\n } = args;\n\n const elementClassName = elementId\n ? (() => {\n // TODO: Overrides for specific elements are mostly here for backwards\n // compatibility. They should be removed in the next major version.\n if (\n elementId === \"primaryButton\" ||\n elementId === \"secondaryButton\" ||\n elementId === \"destructiveButton\"\n ) {\n return namespaceClassNames(\"button\");\n }\n\n if (elementId === \"iconButton\") {\n return namespaceClassNames(\"button\", \"icon-button\");\n }\n\n if (\n elementId === \"primaryMenuItem\" ||\n elementId === \"destructiveMenuItem\"\n ) {\n return namespaceClassNames(\"menu-item\");\n }\n\n if (elementId === \"textfield\") {\n return namespaceClassNames(elementId, \"text-field\");\n }\n\n return namespaceClassNames(fastKebabCase(elementId));\n })()\n : undefined;\n\n const props: DomProps = {\n ...passthroughProps,\n className: cx(\n className,\n isWidgetRoot && namespaceClassNames(\"widget\"),\n elementClassName,\n ),\n };\n\n if (widgetId) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-widget-id`] = widgetId;\n }\n\n if (isWidgetRoot) {\n widgetState ??= \"resolved\";\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-widget-state`] =\n widgetState;\n }\n\n if (dataAttributes) {\n for (const [key, value] of Object.entries(dataAttributes)) {\n if (value != null) {\n const parts = [widgetId, elementId, key]\n .filter((v) => v != null)\n .map(fastKebabCase)\n .join(\"-\");\n if (parts) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-${parts}`] = value;\n }\n }\n }\n }\n\n if (elementId) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-element`] =\n fastKebabCase(elementId);\n }\n\n return props;\n}\n\n/**\n * Opt for simplicity and performance over capturing edge cases. Input strings\n * are expected to only be alphabetic.\n */\nfunction fastKebabCase(alphaString: string) {\n return alphaString.replace(/([A-Z])/g, \"-$1\").toLowerCase();\n}\n\nexport function parseUserAgent(userAgent?: string | null) {\n const browser = Bowser.getParser(userAgent ?? \"\");\n const browserName = browser.getBrowserName().replace(/^Mobile\\s*/i, \"\");\n const osName = browser.getOSName();\n const pretty = [browserName, osName].filter(Boolean).join(\" on \");\n\n return { pretty, isMobile: browser.getPlatformType() === \"mobile\" };\n}\n\nexport function getUserLocation(\n location?: {\n cityName: string;\n countryISOCode: string;\n } | null,\n ipAddress?: string | null,\n) {\n if (location) {\n return (\n [location.cityName, location.countryISOCode].filter(Boolean).join(\", \") ||\n \"Unknown location\"\n );\n }\n\n if (ipAddress) {\n return ipAddress;\n }\n\n return \"Unknown location\";\n}\n\nexport function unreachable(value: never): never {\n throw new TypeError(`Unreachable code: ${value}`);\n}\n\nexport function pluralize(word = \"\", amount = 0, showAmount = true): string {\n return `${showAmount ? `${amount} ` : \"\"}${word}${amount === 1 ? \"\" : \"s\"}`;\n}\n\n// Props that all widgets should accept.\nexport interface WidgetRootDomProps {\n className?: string;\n}\n\nexport type WidgetRootState = \"loading\" | \"error\" | \"resolved\";\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/utils.ts"],"sourcesContent":["import { Member } from \"../api/endpoint.js\";\nimport Bowser from \"bowser\";\nimport cx from \"clsx\";\nimport {\n WIDGETS_CLASS_NAMESPACE,\n WIDGETS_DATA_ATTRIBUTE_NAMESPACE,\n} from \"./constants.js\";\nimport type { Elements } from \"./elements.js\";\n\nexport const canUseDOM = !!(\n typeof window !== \"undefined\" &&\n window.document &&\n window.document.createElement\n);\n\nexport function getBestName({\n firstName,\n lastName,\n}: Pick<Member, \"firstName\" | \"lastName\">) {\n return [firstName, lastName].filter(Boolean).join(\" \") || null;\n}\n\nexport function getComparativeReadableDate(\n now: Date,\n then: Date,\n options?: { timeZone?: string },\n): string {\n const timeSince = now.getTime() - then.getTime();\n\n // Has it been less than a minute?\n if (timeSince < 60_000) {\n return \"Just now\";\n }\n\n // Has it been less than an hour?\n if (timeSince < 3_600_000) {\n const timePassed = Math.floor(timeSince / 60_000);\n return timePassed === 1 ? \"1 minute ago\" : `${timePassed} minutes ago`;\n }\n\n // Has it been less than a day?\n if (timeSince < 86_400_000) {\n const timePassed = Math.floor(timeSince / 3_600_000);\n return timePassed === 1 ? \"1 hour ago\" : `${timePassed} hours ago`;\n }\n\n // Has it been less than a week?\n if (timeSince < 604_800_000) {\n const timePassed = Math.floor(timeSince / 86_400_000);\n return timePassed === 1 ? \"1 day ago\" : `${timePassed} days ago`;\n }\n\n // Has it been less than a month?\n if (timeSince < 2_592_000_000) {\n const timePassed = Math.floor(timeSince / 604_800_000);\n return timePassed === 1 ? \"1 week ago\" : `${timePassed} weeks ago`;\n }\n\n // Any later?\n return then.toLocaleDateString(\"en-US\", {\n timeZone: options?.timeZone,\n month: \"long\",\n day: \"numeric\",\n // omit year if it's the same as the current year\n year: now.getFullYear() !== then.getFullYear() ? \"numeric\" : undefined,\n });\n}\n\nexport function isObjectLike(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function isErrorLike(\n value: unknown,\n): value is Record<string, unknown> & { message: string } {\n return isObjectLike(value) && typeof value.message === \"string\";\n}\n\nexport function isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"then\" in value &&\n typeof value.then === \"function\"\n );\n}\n\nexport async function parseErrorResponse(\n response: Response,\n): Promise<{ message: string; status: number }> {\n try {\n const json = await response.json();\n if (!isObjectLike(json) || typeof json.message !== \"string\") {\n return {\n status: response.status,\n message: response.statusText,\n };\n }\n return {\n ...json,\n status: response.status,\n message: json.message || response.statusText,\n };\n } catch {\n return {\n status: response.status,\n message: response.statusText,\n };\n }\n}\n\nexport function namespaceClassNames(\n ...classNames: (string | undefined | null | boolean)[]\n): string {\n return classNames\n .filter(Boolean)\n .map((className) => `${WIDGETS_CLASS_NAMESPACE}-${className}`)\n .join(\" \");\n}\n\ninterface CommonDomArgs {\n className?: string | undefined | null;\n dataAttributes?: Record<string, string | boolean | undefined | null>;\n}\n\ninterface WidgetRootDomArgs {\n isWidgetRoot: true;\n widgetId: string;\n elementId?: never;\n widgetState: WidgetRootState;\n}\n\ninterface WidgetElementDomArgs {\n isWidgetRoot?: false;\n widgetId?: string;\n elementId?: keyof Elements;\n widgetState?: never;\n className: string | undefined | null;\n}\n\ntype DomArgs = CommonDomArgs & (WidgetRootDomArgs | WidgetElementDomArgs);\n\ntype DataAttributeProps = {\n [K in `data-${string}`]?: string | boolean;\n};\n\ntype DomProps = {\n className: string | undefined;\n} & DataAttributeProps;\n\nexport function getDomProps(args: DomArgs) {\n let {\n className,\n dataAttributes,\n isWidgetRoot = false,\n widgetId,\n elementId,\n widgetState,\n ...passthroughProps\n } = args;\n\n const elementClassName = elementId\n ? (() => {\n // TODO: Overrides for specific elements are mostly here for backwards\n // compatibility. They should be removed in the next major version.\n if (\n elementId === \"primaryButton\" ||\n elementId === \"secondaryButton\" ||\n elementId === \"destructiveButton\"\n ) {\n return namespaceClassNames(\"button\");\n }\n\n if (elementId === \"iconButton\") {\n return namespaceClassNames(\"button\", \"icon-button\");\n }\n\n if (\n elementId === \"primaryMenuItem\" ||\n elementId === \"destructiveMenuItem\"\n ) {\n return namespaceClassNames(\"menu-item\");\n }\n\n if (elementId === \"textfield\") {\n return namespaceClassNames(elementId, \"text-field\");\n }\n\n return namespaceClassNames(fastKebabCase(elementId));\n })()\n : undefined;\n\n const props: DomProps = {\n ...passthroughProps,\n className: cx(\n className,\n isWidgetRoot && namespaceClassNames(\"widget\"),\n elementClassName,\n ),\n };\n\n if (widgetId) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-widget-id`] = widgetId;\n }\n\n if (isWidgetRoot) {\n widgetState ??= \"resolved\";\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-widget-state`] =\n widgetState;\n }\n\n if (dataAttributes) {\n for (const [key, value] of Object.entries(dataAttributes)) {\n if (value != null) {\n const parts = [widgetId, elementId, key]\n .filter((v) => v != null)\n .map(fastKebabCase)\n .join(\"-\");\n if (parts) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-${parts}`] = value;\n }\n }\n }\n }\n\n if (elementId) {\n props[`data-${WIDGETS_DATA_ATTRIBUTE_NAMESPACE}-element`] =\n fastKebabCase(elementId);\n }\n\n return props;\n}\n\n/**\n * Opt for simplicity and performance over capturing edge cases. Input strings\n * are expected to only be alphabetic.\n */\nfunction fastKebabCase(alphaString: string) {\n return alphaString.replace(/([A-Z])/g, \"-$1\").toLowerCase();\n}\n\nexport function parseUserAgent(userAgent?: string | null) {\n const browser = Bowser.getParser(userAgent ?? \"\");\n const browserName = browser.getBrowserName().replace(/^Mobile\\s*/i, \"\");\n const osName = browser.getOSName();\n const pretty = [browserName, osName].filter(Boolean).join(\" on \");\n\n return { pretty, isMobile: browser.getPlatformType() === \"mobile\" };\n}\n\nexport function getUserLocation(\n location?: {\n cityName: string;\n countryISOCode: string;\n } | null,\n ipAddress?: string | null,\n) {\n if (location) {\n return (\n [location.cityName, location.countryISOCode].filter(Boolean).join(\", \") ||\n \"Unknown location\"\n );\n }\n\n if (ipAddress) {\n return ipAddress;\n }\n\n return \"Unknown location\";\n}\n\nexport function unreachable(value: never): never {\n throw new TypeError(`Unreachable code: ${value}`);\n}\n\nexport function pluralize(word = \"\", amount = 0, showAmount = true): string {\n return `${showAmount ? `${amount} ` : \"\"}${word}${amount === 1 ? \"\" : \"s\"}`;\n}\n\n// Props that all widgets should accept.\nexport interface WidgetRootDomProps {\n className?: string;\n}\n\nexport type WidgetRootState = \"loading\" | \"error\" | \"resolved\";\n"],"mappings":"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","names":[]}
@@ -0,0 +1,3 @@
1
+ declare function useWidgetsInvalidator(): () => Promise<void>;
2
+
3
+ export { useWidgetsInvalidator as unstable_useWidgetsInvalidator };
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+ import { useQueryClient } from "@tanstack/react-query";
3
+ function useWidgetsInvalidator() {
4
+ let queryClient;
5
+ try {
6
+ queryClient = useQueryClient();
7
+ } catch {
8
+ throw Error(
9
+ "useWidgetsInvalidation must be used within the `WorkOsWidgets` provider component"
10
+ );
11
+ }
12
+ return React.useCallback(async () => {
13
+ await queryClient.invalidateQueries({ queryKey: ["authToken"] });
14
+ await new Promise((resolve) => setTimeout(resolve, 1));
15
+ return queryClient.invalidateQueries({
16
+ predicate: (query) => query.queryKey.some(
17
+ (key) => typeof key === "string" && key.startsWith("/_widgets/")
18
+ )
19
+ });
20
+ }, [queryClient]);
21
+ }
22
+ export {
23
+ useWidgetsInvalidator as unstable_useWidgetsInvalidator
24
+ };
25
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils.ts"],"sourcesContent":["import * as React from \"react\";\nimport { useQueryClient, type QueryClient } from \"@tanstack/react-query\";\n\nfunction useWidgetsInvalidator() {\n let queryClient: QueryClient;\n try {\n queryClient = useQueryClient();\n } catch {\n throw Error(\n \"useWidgetsInvalidation must be used within the `WorkOsWidgets` provider component\",\n );\n }\n\n return React.useCallback(async () => {\n await queryClient.invalidateQueries({ queryKey: [\"authToken\"] });\n // TODO: Unclear why, but invalidating other widgets' queries immediately\n // after the authToken invalidation (even though it's async?) doesn't work,\n // and We end up with stale data. Waiting for the next tick fixes this.\n await new Promise((resolve) => setTimeout(resolve, 1));\n return queryClient.invalidateQueries({\n predicate: (query) =>\n query.queryKey.some(\n (key) => typeof key === \"string\" && key.startsWith(\"/_widgets/\"),\n ),\n });\n }, [queryClient]);\n}\n\nexport { useWidgetsInvalidator as unstable_useWidgetsInvalidator };\n"],"mappings":"AAAA,YAAY,WAAW;AACvB,SAAS,sBAAwC;AAEjD,SAAS,wBAAwB;AAC/B,MAAI;AACJ,MAAI;AACF,kBAAc,eAAe;AAAA,EAC/B,QAAQ;AACN,UAAM;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAEA,SAAO,MAAM,YAAY,YAAY;AACnC,UAAM,YAAY,kBAAkB,EAAE,UAAU,CAAC,WAAW,EAAE,CAAC;AAI/D,UAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,CAAC,CAAC;AACrD,WAAO,YAAY,kBAAkB;AAAA,MACnC,WAAW,CAAC,UACV,MAAM,SAAS;AAAA,QACb,CAAC,QAAQ,OAAO,QAAQ,YAAY,IAAI,WAAW,YAAY;AAAA,MACjE;AAAA,IACJ,CAAC;AAAA,EACH,GAAG,CAAC,WAAW,CAAC;AAClB;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workos-inc/widgets",
3
- "version": "1.7.0-pre.0",
3
+ "version": "1.7.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -14,6 +14,16 @@
14
14
  "default": "./dist/cjs/index.cjs"
15
15
  }
16
16
  },
17
+ "./utils": {
18
+ "import": {
19
+ "types": "./dist/esm/utils.d.ts",
20
+ "default": "./dist/esm/utils.js"
21
+ },
22
+ "require": {
23
+ "types": "./dist/cjs/utils.d.cts",
24
+ "default": "./dist/cjs/utils.cjs"
25
+ }
26
+ },
17
27
  "./*": {
18
28
  "import": {
19
29
  "types": "./dist/esm/*.client.d.ts",