@flipdish/ui-library 0.32.1 → 0.33.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.
- package/dist/components/atoms/Avatar/components/AvatarLabelGroup.cjs +6 -4
- package/dist/components/atoms/Avatar/components/AvatarLabelGroup.cjs.map +1 -1
- package/dist/components/atoms/Avatar/components/AvatarLabelGroup.d.ts +7 -1
- package/dist/components/atoms/Avatar/components/AvatarLabelGroup.d.ts.map +1 -1
- package/dist/components/atoms/Avatar/components/AvatarLabelGroup.js +6 -4
- package/dist/components/atoms/Avatar/components/AvatarLabelGroup.js.map +1 -1
- package/dist/components/atoms/Badge/badge.types.cjs.map +1 -1
- package/dist/components/atoms/Badge/badge.types.d.ts +2 -1
- package/dist/components/atoms/Badge/badge.types.d.ts.map +1 -1
- package/dist/components/atoms/Badge/badge.types.js.map +1 -1
- package/dist/components/atoms/Badge/index.cjs +2 -1
- package/dist/components/atoms/Badge/index.cjs.map +1 -1
- package/dist/components/atoms/Badge/index.d.ts.map +1 -1
- package/dist/components/atoms/Badge/index.js +2 -1
- package/dist/components/atoms/Badge/index.js.map +1 -1
- package/dist/components/atoms/Card/index.cjs +28 -0
- package/dist/components/atoms/Card/index.cjs.map +1 -0
- package/dist/components/atoms/Card/index.d.ts +20 -0
- package/dist/components/atoms/Card/index.d.ts.map +1 -0
- package/dist/components/atoms/Card/index.js +26 -0
- package/dist/components/atoms/Card/index.js.map +1 -0
- package/dist/components/atoms/CopyButton/index.cjs +27 -0
- package/dist/components/atoms/CopyButton/index.cjs.map +1 -0
- package/dist/components/atoms/CopyButton/index.d.ts +28 -0
- package/dist/components/atoms/CopyButton/index.d.ts.map +1 -0
- package/dist/components/atoms/CopyButton/index.js +25 -0
- package/dist/components/atoms/CopyButton/index.js.map +1 -0
- package/dist/components/atoms/Flag/flag.types.d.ts +6 -0
- package/dist/components/atoms/Flag/flag.types.d.ts.map +1 -0
- package/dist/components/atoms/Flag/flag.utils.cjs +45 -0
- package/dist/components/atoms/Flag/flag.utils.cjs.map +1 -0
- package/dist/components/atoms/Flag/flag.utils.d.ts +15 -0
- package/dist/components/atoms/Flag/flag.utils.d.ts.map +1 -0
- package/dist/components/atoms/Flag/flag.utils.js +42 -0
- package/dist/components/atoms/Flag/flag.utils.js.map +1 -0
- package/dist/components/atoms/Flag/index.cjs +47 -0
- package/dist/components/atoms/Flag/index.cjs.map +1 -0
- package/dist/components/atoms/Flag/index.d.ts +27 -0
- package/dist/components/atoms/Flag/index.d.ts.map +1 -0
- package/dist/components/atoms/Flag/index.js +45 -0
- package/dist/components/atoms/Flag/index.js.map +1 -0
- package/dist/components/atoms/SearchInput/index.cjs +32 -0
- package/dist/components/atoms/SearchInput/index.cjs.map +1 -0
- package/dist/components/atoms/SearchInput/index.d.ts +40 -0
- package/dist/components/atoms/SearchInput/index.d.ts.map +1 -0
- package/dist/components/atoms/SearchInput/index.js +30 -0
- package/dist/components/atoms/SearchInput/index.js.map +1 -0
- package/dist/components/molecules/DetailList/detailList.types.d.ts +15 -0
- package/dist/components/molecules/DetailList/detailList.types.d.ts.map +1 -0
- package/dist/components/molecules/DetailList/index.cjs +32 -0
- package/dist/components/molecules/DetailList/index.cjs.map +1 -0
- package/dist/components/molecules/DetailList/index.d.ts +26 -0
- package/dist/components/molecules/DetailList/index.d.ts.map +1 -0
- package/dist/components/molecules/DetailList/index.js +30 -0
- package/dist/components/molecules/DetailList/index.js.map +1 -0
- package/dist/components/molecules/RadioGroup/components/RadioGroupAvatarCard.cjs +43 -0
- package/dist/components/molecules/RadioGroup/components/RadioGroupAvatarCard.cjs.map +1 -0
- package/dist/components/molecules/RadioGroup/components/RadioGroupAvatarCard.d.ts +24 -0
- package/dist/components/molecules/RadioGroup/components/RadioGroupAvatarCard.d.ts.map +1 -0
- package/dist/components/molecules/RadioGroup/components/RadioGroupAvatarCard.js +41 -0
- package/dist/components/molecules/RadioGroup/components/RadioGroupAvatarCard.js.map +1 -0
- package/dist/components/molecules/RadioGroup/index.cjs +2 -0
- package/dist/components/molecules/RadioGroup/index.cjs.map +1 -1
- package/dist/components/molecules/RadioGroup/index.d.ts +2 -0
- package/dist/components/molecules/RadioGroup/index.d.ts.map +1 -1
- package/dist/components/molecules/RadioGroup/index.js +1 -0
- package/dist/components/molecules/RadioGroup/index.js.map +1 -1
- package/dist/components/molecules/RadioGroup/radioGroup.types.d.ts +17 -1
- package/dist/components/molecules/RadioGroup/radioGroup.types.d.ts.map +1 -1
- package/dist/components/organisms/ApplicationHeader/applicationHeader.types.d.ts +8 -2
- package/dist/components/organisms/ApplicationHeader/applicationHeader.types.d.ts.map +1 -1
- package/dist/components/organisms/ApplicationHeader/components/AvatarButton.cjs +4 -1
- package/dist/components/organisms/ApplicationHeader/components/AvatarButton.cjs.map +1 -1
- package/dist/components/organisms/ApplicationHeader/components/AvatarButton.d.ts +2 -1
- package/dist/components/organisms/ApplicationHeader/components/AvatarButton.d.ts.map +1 -1
- package/dist/components/organisms/ApplicationHeader/components/AvatarButton.js +4 -1
- package/dist/components/organisms/ApplicationHeader/components/AvatarButton.js.map +1 -1
- package/dist/components/organisms/ApplicationHeader/index.cjs +1 -1
- package/dist/components/organisms/ApplicationHeader/index.cjs.map +1 -1
- package/dist/components/organisms/ApplicationHeader/index.d.ts.map +1 -1
- package/dist/components/organisms/ApplicationHeader/index.js +1 -1
- package/dist/components/organisms/ApplicationHeader/index.js.map +1 -1
- package/dist/components/organisms/HeaderNavigation/index.cjs +2 -3
- package/dist/components/organisms/HeaderNavigation/index.cjs.map +1 -1
- package/dist/components/organisms/HeaderNavigation/index.d.ts.map +1 -1
- package/dist/components/organisms/HeaderNavigation/index.js +2 -3
- package/dist/components/organisms/HeaderNavigation/index.js.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelContent.cjs +3 -1
- package/dist/components/organisms/SidePanel/components/SidePanelContent.cjs.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelContent.d.ts.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelContent.js +3 -1
- package/dist/components/organisms/SidePanel/components/SidePanelContent.js.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelFooter.cjs +3 -3
- package/dist/components/organisms/SidePanel/components/SidePanelFooter.cjs.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelFooter.d.ts +7 -2
- package/dist/components/organisms/SidePanel/components/SidePanelFooter.d.ts.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelFooter.js +3 -3
- package/dist/components/organisms/SidePanel/components/SidePanelFooter.js.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelHeader.cjs +7 -3
- package/dist/components/organisms/SidePanel/components/SidePanelHeader.cjs.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelHeader.d.ts +6 -2
- package/dist/components/organisms/SidePanel/components/SidePanelHeader.d.ts.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelHeader.js +7 -3
- package/dist/components/organisms/SidePanel/components/SidePanelHeader.js.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelRegion.cjs +8 -3
- package/dist/components/organisms/SidePanel/components/SidePanelRegion.cjs.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelRegion.d.ts +2 -1
- package/dist/components/organisms/SidePanel/components/SidePanelRegion.d.ts.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelRegion.js +8 -3
- package/dist/components/organisms/SidePanel/components/SidePanelRegion.js.map +1 -1
- package/dist/components/organisms/SidePanel/hooks/usePanelFocus.cjs +12 -1
- package/dist/components/organisms/SidePanel/hooks/usePanelFocus.cjs.map +1 -1
- package/dist/components/organisms/SidePanel/hooks/usePanelFocus.d.ts +3 -1
- package/dist/components/organisms/SidePanel/hooks/usePanelFocus.d.ts.map +1 -1
- package/dist/components/organisms/SidePanel/hooks/usePanelFocus.js +13 -2
- package/dist/components/organisms/SidePanel/hooks/usePanelFocus.js.map +1 -1
- package/dist/components/organisms/SidePanel/index.cjs +2 -2
- package/dist/components/organisms/SidePanel/index.cjs.map +1 -1
- package/dist/components/organisms/SidePanel/index.d.ts +3 -1
- package/dist/components/organisms/SidePanel/index.d.ts.map +1 -1
- package/dist/components/organisms/SidePanel/index.js +2 -2
- package/dist/components/organisms/SidePanel/index.js.map +1 -1
- package/dist/native/components/atoms/Card/index.d.ts +12 -0
- package/dist/native/components/atoms/CopyButton/index.d.ts +12 -0
- package/dist/native/components/atoms/Flag/index.d.ts +12 -0
- package/dist/native/components/atoms/SearchInput/index.d.ts +12 -0
- package/dist/native/components/molecules/DetailList/index.d.ts +12 -0
- package/package.json +2 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { getEnvironmentVariable } from '@flipdish/ui-library/utilities/renderUtils';
|
|
2
|
+
|
|
3
|
+
const resolvers = new Map();
|
|
4
|
+
const warnedCodes = new Set();
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a country's name from its ISO 3166-1 alpha-2 code, for the flag's default accessible name.
|
|
7
|
+
* @param code The country code, as `Flag` receives it.
|
|
8
|
+
* @param locale BCP 47 tag the name is written in; the app's locale, so server and client agree.
|
|
9
|
+
* @returns The region name in that locale, or the code itself where `Intl.DisplayNames` is missing or rejects the code or locale.
|
|
10
|
+
*/
|
|
11
|
+
const getCountryName = (code, locale = 'en') => {
|
|
12
|
+
// Built once per locale; `Intl.DisplayNames` is missing from some older runtimes, where the code stands in.
|
|
13
|
+
let resolver = resolvers.get(locale);
|
|
14
|
+
if (resolver === undefined) {
|
|
15
|
+
try {
|
|
16
|
+
resolver = typeof Intl.DisplayNames === 'function' ? new Intl.DisplayNames([locale], { type: 'region' }) : null;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
resolver = null;
|
|
20
|
+
}
|
|
21
|
+
resolvers.set(locale, resolver);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
return resolver?.of(code) ?? code;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return code;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Warns once per unknown country code outside production, so a bad code is visible in development without flooding the console.
|
|
32
|
+
* @param code The code no flag exists for.
|
|
33
|
+
*/
|
|
34
|
+
const warnUnknownCountryOnce = (code) => {
|
|
35
|
+
if (getEnvironmentVariable('NODE_ENV') === 'production' || warnedCodes.has(code))
|
|
36
|
+
return;
|
|
37
|
+
warnedCodes.add(code);
|
|
38
|
+
console.warn(`Flag: no flag for country code "${code}".`);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export { getCountryName, warnUnknownCountryOnce };
|
|
42
|
+
//# sourceMappingURL=flag.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag.utils.js","sources":["../../../../src/components/atoms/Flag/flag.utils.ts"],"sourcesContent":[null],"names":[],"mappings":";;AAEA,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoC;AAC7D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU;AAErC;;;;;AAKG;AACI,MAAM,cAAc,GAAG,CAAC,IAAY,EAAE,MAAM,GAAG,IAAI,KAAY;;IAEpE,IAAI,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC;AACpC,IAAA,IAAI,QAAQ,KAAK,SAAS,EAAE;AAC1B,QAAA,IAAI;AACF,YAAA,QAAQ,GAAG,OAAO,IAAI,CAAC,YAAY,KAAK,UAAU,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI;QACjH;AAAE,QAAA,MAAM;YACN,QAAQ,GAAG,IAAI;QACjB;AACA,QAAA,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;IACjC;AACA,IAAA,IAAI;QACF,OAAO,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI;IACnC;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,IAAI;IACb;AACF;AAEA;;;AAGG;AACI,MAAM,sBAAsB,GAAG,CAAC,IAAY,KAAU;AAC3D,IAAA,IAAI,sBAAsB,CAAC,UAAU,CAAC,KAAK,YAAY,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE;AAClF,IAAA,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;AACrB,IAAA,OAAO,CAAC,IAAI,CAAC,mCAAmC,IAAI,CAAA,EAAA,CAAI,CAAC;AAC3D;;"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var cx = require('@flipdish/ui-library/utilities/cx');
|
|
5
|
+
var testIdUtils = require('@flipdish/ui-library/utilities/testIdUtils');
|
|
6
|
+
var React = require('react');
|
|
7
|
+
var flag_utils = require('./flag.utils.cjs');
|
|
8
|
+
|
|
9
|
+
const toFlagSvg = (set) => {
|
|
10
|
+
const FlagSvg = ({ code, ...props }) => {
|
|
11
|
+
const Svg = set[code];
|
|
12
|
+
if (!Svg) {
|
|
13
|
+
flag_utils.warnUnknownCountryOnce(code);
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return jsxRuntime.jsx(Svg, { ...props });
|
|
17
|
+
};
|
|
18
|
+
return { default: FlagSvg };
|
|
19
|
+
};
|
|
20
|
+
// Each set is every country in one ~53 KB gzip module, so it loads on the first flag of that shape rather than with every importer of `Flag`.
|
|
21
|
+
const FLAG_SVGS = {
|
|
22
|
+
round: React.lazy(() => import('country-flag-icons/react/1x1').then((flags) => toFlagSvg(flags))),
|
|
23
|
+
rectangle: React.lazy(() => import('country-flag-icons/react/3x2').then((flags) => toFlagSvg(flags))),
|
|
24
|
+
};
|
|
25
|
+
// A rectangle keeps the art's 3:2 ratio at the same height as the round flag.
|
|
26
|
+
const SIZES = {
|
|
27
|
+
round: { xs: 'size-4', sm: 'size-5', md: 'size-6', lg: 'size-8' },
|
|
28
|
+
rectangle: { xs: 'h-4 w-6', sm: 'h-5 w-7.5', md: 'h-6 w-9', lg: 'h-8 w-12' },
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* A country's flag from its ISO code, round for inline use beside a label or rectangular where
|
|
32
|
+
* the full flag matters. Each shape is one bundled set from `country-flag-icons` that loads on
|
|
33
|
+
* its first use, so a page costs nothing until it shows a flag and the same after that however
|
|
34
|
+
* many countries it shows.
|
|
35
|
+
*
|
|
36
|
+
* @summary country flag from an ISO country code
|
|
37
|
+
*/
|
|
38
|
+
const Flag = ({ code, size = 'sm', shape = 'round', label, locale, className, 'data-testid': dataTestId, ...props }) => {
|
|
39
|
+
const flagTestId = testIdUtils.useResolvedTestId({ testId: dataTestId, segment: 'flag', rootName: 'flag' });
|
|
40
|
+
const name = label ?? flag_utils.getCountryName(code, locale);
|
|
41
|
+
const isDecorative = name === '';
|
|
42
|
+
const FlagSvg = FLAG_SVGS[shape];
|
|
43
|
+
return (jsxRuntime.jsx(React.Suspense, { fallback: null, children: jsxRuntime.jsx(FlagSvg, { ...props, code: code, "data-testid": flagTestId, role: isDecorative ? undefined : 'img', "aria-label": isDecorative ? undefined : name, "aria-hidden": isDecorative || undefined, title: isDecorative ? undefined : name, className: cx.cx('shrink-0 overflow-hidden', shape === 'round' && 'rounded-full', SIZES[shape][size], className) }) }));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
exports.Flag = Flag;
|
|
47
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/atoms/Flag/index.tsx"],"sourcesContent":[null],"names":["warnUnknownCountryOnce","_jsx","lazy","useResolvedTestId","getCountryName","Suspense","cx"],"mappings":";;;;;;;;AAeA,MAAM,SAAS,GAAG,CAAC,GAAY,KAAI;IACjC,MAAM,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,EAAmC,KAAI;AACtE,QAAA,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC;QACrB,IAAI,CAAC,GAAG,EAAE;YACRA,iCAAsB,CAAC,IAAI,CAAC;AAC5B,YAAA,OAAO,IAAI;QACb;AACA,QAAA,OAAOC,cAAA,CAAC,GAAG,EAAA,EAAA,GAAK,KAAK,GAAI;AAC3B,IAAA,CAAC;AACD,IAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;AAC7B,CAAC;AAED;AACA,MAAM,SAAS,GAAG;IAChB,KAAK,EAAEC,UAAI,CAAC,MAAM,OAAO,8BAA8B,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,KAAgB,CAAC,CAAC,CAAC;IACtG,SAAS,EAAEA,UAAI,CAAC,MAAM,OAAO,8BAA8B,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,KAAgB,CAAC,CAAC,CAAC;CAC3G;AAED;AACA,MAAM,KAAK,GAAgD;AACzD,IAAA,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE;AACjE,IAAA,SAAS,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE;CAC7E;AAiBD;;;;;;;AAOG;AACI,MAAM,IAAI,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,KAAK,EAAa,KAAI;AACvI,IAAA,MAAM,UAAU,GAAGC,6BAAiB,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC/F,MAAM,IAAI,GAAG,KAAK,IAAIC,yBAAc,CAAC,IAAI,EAAE,MAAM,CAAC;AAClD,IAAA,MAAM,YAAY,GAAG,IAAI,KAAK,EAAE;AAChC,IAAA,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC;AAEhC,IAAA,QACEH,cAAA,CAACI,cAAQ,EAAA,EAAC,QAAQ,EAAE,IAAI,EAAA,QAAA,EACtBJ,cAAA,CAAC,OAAO,OACF,KAAK,EACT,IAAI,EAAE,IAAI,iBACG,UAAU,EACvB,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,KAAK,EAAA,YAAA,EAC1B,YAAY,GAAG,SAAS,GAAG,IAAI,EAAA,aAAA,EAC9B,YAAY,IAAI,SAAS,EACtC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,EACtC,SAAS,EAAEK,KAAE,CAAC,0BAA0B,EAAE,KAAK,KAAK,OAAO,IAAI,cAAc,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,EAAA,CAC7G,EAAA,CACO;AAEf;;"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SVGProps } from 'react';
|
|
2
|
+
import type { CountryCode, FlagShape, FlagSize } from './flag.types';
|
|
3
|
+
export type { CountryCode, FlagShape, FlagSize } from './flag.types';
|
|
4
|
+
export interface FlagProps extends Omit<SVGProps<SVGSVGElement>, 'children'> {
|
|
5
|
+
/** ISO 3166-1 alpha-2 code of the country to show. */
|
|
6
|
+
code: CountryCode;
|
|
7
|
+
/** Height: `xs` 16px, `sm` 20px, `md` 24px, `lg` 32px. A rectangle is 3:2, so wider than tall. */
|
|
8
|
+
size?: FlagSize;
|
|
9
|
+
/** `round` clips the square art to a circle; `rectangle` shows the 3:2 flag. */
|
|
10
|
+
shape?: FlagShape;
|
|
11
|
+
/** Accessible name. Defaults to the country's name in `locale`; pass `''` to hide the flag from assistive technology when visible text beside it already names the country. */
|
|
12
|
+
label?: string;
|
|
13
|
+
/** BCP 47 tag the default name is written in. Pass the app's locale rather than reading the browser's, so server and client render the same name. */
|
|
14
|
+
locale?: string;
|
|
15
|
+
/** Overrides the `data-testid` (defaults to `fd-flag`). */
|
|
16
|
+
'data-testid'?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* A country's flag from its ISO code, round for inline use beside a label or rectangular where
|
|
20
|
+
* the full flag matters. Each shape is one bundled set from `country-flag-icons` that loads on
|
|
21
|
+
* its first use, so a page costs nothing until it shows a flag and the same after that however
|
|
22
|
+
* many countries it shows.
|
|
23
|
+
*
|
|
24
|
+
* @summary country flag from an ISO country code
|
|
25
|
+
*/
|
|
26
|
+
export declare const Flag: ({ code, size, shape, label, locale, className, "data-testid": dataTestId, ...props }: FlagProps) => import("react").JSX.Element;
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/atoms/Flag/index.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAgB,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGrE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AA8BrE,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC;IAC1E,sDAAsD;IACtD,IAAI,EAAE,WAAW,CAAC;IAClB,kGAAkG;IAClG,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,gFAAgF;IAChF,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,+KAA+K;IAC/K,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qJAAqJ;IACrJ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,GAAI,sFAAuG,SAAS,gCAoBpI,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { cx } from '@flipdish/ui-library/utilities/cx';
|
|
3
|
+
import { useResolvedTestId } from '@flipdish/ui-library/utilities/testIdUtils';
|
|
4
|
+
import { lazy, Suspense } from 'react';
|
|
5
|
+
import { warnUnknownCountryOnce, getCountryName } from './flag.utils.js';
|
|
6
|
+
|
|
7
|
+
const toFlagSvg = (set) => {
|
|
8
|
+
const FlagSvg = ({ code, ...props }) => {
|
|
9
|
+
const Svg = set[code];
|
|
10
|
+
if (!Svg) {
|
|
11
|
+
warnUnknownCountryOnce(code);
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return jsx(Svg, { ...props });
|
|
15
|
+
};
|
|
16
|
+
return { default: FlagSvg };
|
|
17
|
+
};
|
|
18
|
+
// Each set is every country in one ~53 KB gzip module, so it loads on the first flag of that shape rather than with every importer of `Flag`.
|
|
19
|
+
const FLAG_SVGS = {
|
|
20
|
+
round: lazy(() => import('country-flag-icons/react/1x1').then((flags) => toFlagSvg(flags))),
|
|
21
|
+
rectangle: lazy(() => import('country-flag-icons/react/3x2').then((flags) => toFlagSvg(flags))),
|
|
22
|
+
};
|
|
23
|
+
// A rectangle keeps the art's 3:2 ratio at the same height as the round flag.
|
|
24
|
+
const SIZES = {
|
|
25
|
+
round: { xs: 'size-4', sm: 'size-5', md: 'size-6', lg: 'size-8' },
|
|
26
|
+
rectangle: { xs: 'h-4 w-6', sm: 'h-5 w-7.5', md: 'h-6 w-9', lg: 'h-8 w-12' },
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* A country's flag from its ISO code, round for inline use beside a label or rectangular where
|
|
30
|
+
* the full flag matters. Each shape is one bundled set from `country-flag-icons` that loads on
|
|
31
|
+
* its first use, so a page costs nothing until it shows a flag and the same after that however
|
|
32
|
+
* many countries it shows.
|
|
33
|
+
*
|
|
34
|
+
* @summary country flag from an ISO country code
|
|
35
|
+
*/
|
|
36
|
+
const Flag = ({ code, size = 'sm', shape = 'round', label, locale, className, 'data-testid': dataTestId, ...props }) => {
|
|
37
|
+
const flagTestId = useResolvedTestId({ testId: dataTestId, segment: 'flag', rootName: 'flag' });
|
|
38
|
+
const name = label ?? getCountryName(code, locale);
|
|
39
|
+
const isDecorative = name === '';
|
|
40
|
+
const FlagSvg = FLAG_SVGS[shape];
|
|
41
|
+
return (jsx(Suspense, { fallback: null, children: jsx(FlagSvg, { ...props, code: code, "data-testid": flagTestId, role: isDecorative ? undefined : 'img', "aria-label": isDecorative ? undefined : name, "aria-hidden": isDecorative || undefined, title: isDecorative ? undefined : name, className: cx('shrink-0 overflow-hidden', shape === 'round' && 'rounded-full', SIZES[shape][size], className) }) }));
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { Flag };
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/Flag/index.tsx"],"sourcesContent":[null],"names":["_jsx"],"mappings":";;;;;;AAeA,MAAM,SAAS,GAAG,CAAC,GAAY,KAAI;IACjC,MAAM,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,EAAmC,KAAI;AACtE,QAAA,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC;QACrB,IAAI,CAAC,GAAG,EAAE;YACR,sBAAsB,CAAC,IAAI,CAAC;AAC5B,YAAA,OAAO,IAAI;QACb;AACA,QAAA,OAAOA,GAAA,CAAC,GAAG,EAAA,EAAA,GAAK,KAAK,GAAI;AAC3B,IAAA,CAAC;AACD,IAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE;AAC7B,CAAC;AAED;AACA,MAAM,SAAS,GAAG;IAChB,KAAK,EAAE,IAAI,CAAC,MAAM,OAAO,8BAA8B,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,KAAgB,CAAC,CAAC,CAAC;IACtG,SAAS,EAAE,IAAI,CAAC,MAAM,OAAO,8BAA8B,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,KAAgB,CAAC,CAAC,CAAC;CAC3G;AAED;AACA,MAAM,KAAK,GAAgD;AACzD,IAAA,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE;AACjE,IAAA,SAAS,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,UAAU,EAAE;CAC7E;AAiBD;;;;;;;AAOG;AACI,MAAM,IAAI,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,KAAK,EAAa,KAAI;AACvI,IAAA,MAAM,UAAU,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC/F,MAAM,IAAI,GAAG,KAAK,IAAI,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC;AAClD,IAAA,MAAM,YAAY,GAAG,IAAI,KAAK,EAAE;AAChC,IAAA,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC;AAEhC,IAAA,QACEA,GAAA,CAAC,QAAQ,EAAA,EAAC,QAAQ,EAAE,IAAI,EAAA,QAAA,EACtBA,GAAA,CAAC,OAAO,OACF,KAAK,EACT,IAAI,EAAE,IAAI,iBACG,UAAU,EACvB,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,KAAK,EAAA,YAAA,EAC1B,YAAY,GAAG,SAAS,GAAG,IAAI,EAAA,aAAA,EAC9B,YAAY,IAAI,SAAS,EACtC,KAAK,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,EACtC,SAAS,EAAE,EAAE,CAAC,0BAA0B,EAAE,KAAK,KAAK,OAAO,IAAI,cAAc,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,EAAA,CAC7G,EAAA,CACO;AAEf;;"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var uiIcons = require('@flipdish/ui-icons');
|
|
5
|
+
var Input = require('@flipdish/ui-library/components/atoms/Input');
|
|
6
|
+
var cx = require('@flipdish/ui-library/utilities/cx');
|
|
7
|
+
var testIdUtils = require('@flipdish/ui-library/utilities/testIdUtils');
|
|
8
|
+
var reactAriaComponents = require('react-aria-components');
|
|
9
|
+
var useHotkeyHint = require('../../../hooks/__internal__/useHotkeyHint/useHotkeyHint.cjs');
|
|
10
|
+
|
|
11
|
+
const sizes = cx.sortCx({
|
|
12
|
+
sm: { input: 'py-2 pr-9 pl-9 text-sm', icon: 'left-3 size-4 stroke-[2.25px]', clear: 'right-2', shortcut: 'pr-1.5' },
|
|
13
|
+
md: { input: 'py-2 pr-9 pl-10 text-md', icon: 'left-3 size-5', clear: 'right-2', shortcut: 'pr-2' },
|
|
14
|
+
lg: { input: 'py-2.5 pr-9.5 pl-10.5 text-md', icon: 'left-3.5 size-5', clear: 'right-2.5', shortcut: 'pr-2.5' },
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* A search box with a magnifier, a clear button once it holds text, and Escape to clear. Use it
|
|
18
|
+
* wherever typing filters a list or table; for a field that collects a value, use `Input`.
|
|
19
|
+
*
|
|
20
|
+
* @summary search box that filters as you type and clears in one press
|
|
21
|
+
*/
|
|
22
|
+
const SearchInput = ({ label, hint, placeholder, size = 'md', clearLabel = 'Clear search', shortcut, className, wrapperClassName, inputClassName, ref, 'data-testid': dataTestId, ...props }) => {
|
|
23
|
+
const inputTestId = testIdUtils.useResolvedTestId({ testId: dataTestId, segment: 'search-input', rootName: 'search-input' });
|
|
24
|
+
const shortcutLabel = useHotkeyHint.useHotkeyHint(shortcut === true ? 'mod+k' : shortcut || null);
|
|
25
|
+
return (jsxRuntime.jsx(reactAriaComponents.SearchField, { "aria-label": label ? undefined : placeholder, ...props, className: cx.cx('group/search flex h-max w-full flex-col items-start gap-1.5', className), children: ({ isInvalid, isDisabled }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [label && jsxRuntime.jsx(Input.Label, { isInvalid: isInvalid, children: label }), jsxRuntime.jsxs(reactAriaComponents.Group, { isDisabled: isDisabled, isInvalid: isInvalid, className: ({ isFocusWithin }) => cx.cx('relative flex w-full items-center rounded-lg bg-primary shadow-xs ring-1 ring-primary transition-shadow duration-100 ease-linear ring-inset', isFocusWithin && !isDisabled && 'ring-2 ring-brand', isDisabled && 'cursor-not-allowed opacity-50', isInvalid && 'ring-error_subtle', isInvalid && isFocusWithin && 'ring-2 ring-error', wrapperClassName), children: [jsxRuntime.jsx(uiIcons.SearchLg, { "aria-hidden": "true", className: cx.cx('pointer-events-none absolute text-fg-quaternary', sizes[size].icon) }), jsxRuntime.jsx(reactAriaComponents.Input, { ref: ref, "data-testid": inputTestId, placeholder: placeholder, className: cx.cx(
|
|
26
|
+
// The browser draws its own cancel control on a search input; the clear button below replaces it.
|
|
27
|
+
'm-0 w-full bg-transparent text-primary ring-0 outline-hidden placeholder:text-placeholder disabled:cursor-not-allowed [&::-webkit-search-cancel-button]:hidden', sizes[size].input, inputClassName) }), jsxRuntime.jsx(reactAriaComponents.Button, { "aria-label": clearLabel, "data-testid": testIdUtils.joinTestId(inputTestId, 'clear'), className: cx.cx('absolute flex cursor-pointer items-center justify-center rounded-md p-1 text-fg-quaternary outline-focus-ring transition duration-100 ease-linear group-data-empty/search:hidden group-data-disabled/search:hidden group-data-readonly/search:hidden hover:text-fg-quaternary_hover focus-visible:outline-2', sizes[size].clear), children: jsxRuntime.jsx(uiIcons.XClose, { "aria-hidden": "true", className: "size-4 stroke-[2.25px]" }) }), shortcut && (jsxRuntime.jsx("div", { className: cx.cx('pointer-events-none absolute inset-y-0.5 right-0.5 z-10 hidden items-center rounded-r-[inherit] bg-linear-to-r from-transparent to-bg-primary to-40% pl-8 group-data-empty/search:md:flex', sizes[size].shortcut), children: jsxRuntime.jsx("span", { "aria-hidden": "true", className: "rounded px-1 py-px text-xs font-medium text-quaternary ring-1 ring-secondary select-none ring-inset", children: shortcutLabel }) }))] }), hint && jsxRuntime.jsx(Input.HintText, { isInvalid: isInvalid, children: hint })] })) }));
|
|
28
|
+
};
|
|
29
|
+
SearchInput.displayName = 'SearchInput';
|
|
30
|
+
|
|
31
|
+
exports.SearchInput = SearchInput;
|
|
32
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/atoms/SearchInput/index.tsx"],"sourcesContent":[null],"names":["sortCx","useResolvedTestId","useHotkeyHint","_jsx","AriaSearchField","cx","_jsxs","_Fragment","Label","AriaGroup","SearchLg","AriaInput","AriaButton","joinTestId","XClose","HintText"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ReactNode, Ref } from 'react';
|
|
2
|
+
import type { SearchFieldProps as AriaSearchFieldProps } from 'react-aria-components';
|
|
3
|
+
export interface SearchInputProps extends Omit<AriaSearchFieldProps, 'children' | 'className' | 'style'> {
|
|
4
|
+
/** Visible label above the field. Without one, pass `aria-label`; the placeholder alone does not name the field once it holds a value. */
|
|
5
|
+
label?: string;
|
|
6
|
+
/** Helper text under the field. */
|
|
7
|
+
hint?: ReactNode;
|
|
8
|
+
/** Placeholder shown while the field is empty. */
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
/** Height, padding and text size. */
|
|
11
|
+
size?: 'sm' | 'md' | 'lg';
|
|
12
|
+
/** Accessible name of the clear button. */
|
|
13
|
+
clearLabel?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Keyboard shortcut hint shown while the field is empty. `true` shows the search shortcut (⌘K on
|
|
16
|
+
* macOS, Ctrl K elsewhere); a shortcut such as `mod+j` is drawn for the user's platform.
|
|
17
|
+
*/
|
|
18
|
+
shortcut?: string | boolean;
|
|
19
|
+
/** Extra classes merged onto the outer field. */
|
|
20
|
+
className?: string;
|
|
21
|
+
/** Extra classes merged onto the bordered group around the input. */
|
|
22
|
+
wrapperClassName?: string;
|
|
23
|
+
/** Extra classes merged onto the `<input>`. */
|
|
24
|
+
inputClassName?: string;
|
|
25
|
+
/** Ref forwarded to the `<input>`. */
|
|
26
|
+
ref?: Ref<HTMLInputElement>;
|
|
27
|
+
/** Overrides the `<input>`'s `data-testid` (defaults to `fd-search-input`). The clear button derives `<root>--clear`. */
|
|
28
|
+
'data-testid'?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A search box with a magnifier, a clear button once it holds text, and Escape to clear. Use it
|
|
32
|
+
* wherever typing filters a list or table; for a field that collects a value, use `Input`.
|
|
33
|
+
*
|
|
34
|
+
* @summary search box that filters as you type and clears in one press
|
|
35
|
+
*/
|
|
36
|
+
export declare const SearchInput: {
|
|
37
|
+
({ label, hint, placeholder, size, clearLabel, shortcut, className, wrapperClassName, inputClassName, ref, "data-testid": dataTestId, ...props }: SearchInputProps): import("react").JSX.Element;
|
|
38
|
+
displayName: string;
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/atoms/SearchInput/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAUtF,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC;IACtG,0IAA0I;IAC1I,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sCAAsC;IACtC,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC5B,yHAAyH;IACzH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW;sJAarB,gBAAgB;;CAuElB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { SearchLg, XClose } from '@flipdish/ui-icons';
|
|
3
|
+
import { Label, HintText } from '@flipdish/ui-library/components/atoms/Input';
|
|
4
|
+
import { sortCx, cx } from '@flipdish/ui-library/utilities/cx';
|
|
5
|
+
import { useResolvedTestId, joinTestId } from '@flipdish/ui-library/utilities/testIdUtils';
|
|
6
|
+
import { SearchField, Group, Input, Button } from 'react-aria-components';
|
|
7
|
+
import { useHotkeyHint } from '../../../hooks/__internal__/useHotkeyHint/useHotkeyHint.js';
|
|
8
|
+
|
|
9
|
+
const sizes = sortCx({
|
|
10
|
+
sm: { input: 'py-2 pr-9 pl-9 text-sm', icon: 'left-3 size-4 stroke-[2.25px]', clear: 'right-2', shortcut: 'pr-1.5' },
|
|
11
|
+
md: { input: 'py-2 pr-9 pl-10 text-md', icon: 'left-3 size-5', clear: 'right-2', shortcut: 'pr-2' },
|
|
12
|
+
lg: { input: 'py-2.5 pr-9.5 pl-10.5 text-md', icon: 'left-3.5 size-5', clear: 'right-2.5', shortcut: 'pr-2.5' },
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* A search box with a magnifier, a clear button once it holds text, and Escape to clear. Use it
|
|
16
|
+
* wherever typing filters a list or table; for a field that collects a value, use `Input`.
|
|
17
|
+
*
|
|
18
|
+
* @summary search box that filters as you type and clears in one press
|
|
19
|
+
*/
|
|
20
|
+
const SearchInput = ({ label, hint, placeholder, size = 'md', clearLabel = 'Clear search', shortcut, className, wrapperClassName, inputClassName, ref, 'data-testid': dataTestId, ...props }) => {
|
|
21
|
+
const inputTestId = useResolvedTestId({ testId: dataTestId, segment: 'search-input', rootName: 'search-input' });
|
|
22
|
+
const shortcutLabel = useHotkeyHint(shortcut === true ? 'mod+k' : shortcut || null);
|
|
23
|
+
return (jsx(SearchField, { "aria-label": label ? undefined : placeholder, ...props, className: cx('group/search flex h-max w-full flex-col items-start gap-1.5', className), children: ({ isInvalid, isDisabled }) => (jsxs(Fragment, { children: [label && jsx(Label, { isInvalid: isInvalid, children: label }), jsxs(Group, { isDisabled: isDisabled, isInvalid: isInvalid, className: ({ isFocusWithin }) => cx('relative flex w-full items-center rounded-lg bg-primary shadow-xs ring-1 ring-primary transition-shadow duration-100 ease-linear ring-inset', isFocusWithin && !isDisabled && 'ring-2 ring-brand', isDisabled && 'cursor-not-allowed opacity-50', isInvalid && 'ring-error_subtle', isInvalid && isFocusWithin && 'ring-2 ring-error', wrapperClassName), children: [jsx(SearchLg, { "aria-hidden": "true", className: cx('pointer-events-none absolute text-fg-quaternary', sizes[size].icon) }), jsx(Input, { ref: ref, "data-testid": inputTestId, placeholder: placeholder, className: cx(
|
|
24
|
+
// The browser draws its own cancel control on a search input; the clear button below replaces it.
|
|
25
|
+
'm-0 w-full bg-transparent text-primary ring-0 outline-hidden placeholder:text-placeholder disabled:cursor-not-allowed [&::-webkit-search-cancel-button]:hidden', sizes[size].input, inputClassName) }), jsx(Button, { "aria-label": clearLabel, "data-testid": joinTestId(inputTestId, 'clear'), className: cx('absolute flex cursor-pointer items-center justify-center rounded-md p-1 text-fg-quaternary outline-focus-ring transition duration-100 ease-linear group-data-empty/search:hidden group-data-disabled/search:hidden group-data-readonly/search:hidden hover:text-fg-quaternary_hover focus-visible:outline-2', sizes[size].clear), children: jsx(XClose, { "aria-hidden": "true", className: "size-4 stroke-[2.25px]" }) }), shortcut && (jsx("div", { className: cx('pointer-events-none absolute inset-y-0.5 right-0.5 z-10 hidden items-center rounded-r-[inherit] bg-linear-to-r from-transparent to-bg-primary to-40% pl-8 group-data-empty/search:md:flex', sizes[size].shortcut), children: jsx("span", { "aria-hidden": "true", className: "rounded px-1 py-px text-xs font-medium text-quaternary ring-1 ring-secondary select-none ring-inset", children: shortcutLabel }) }))] }), hint && jsx(HintText, { isInvalid: isInvalid, children: hint })] })) }));
|
|
26
|
+
};
|
|
27
|
+
SearchInput.displayName = 'SearchInput';
|
|
28
|
+
|
|
29
|
+
export { SearchInput };
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/atoms/SearchInput/index.tsx"],"sourcesContent":[null],"names":["_jsx","AriaSearchField","_jsxs","_Fragment","AriaGroup","AriaInput","AriaButton"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { FC, ReactElement, ReactNode } from 'react';
|
|
2
|
+
/** One row of a `DetailList`: an icon, the label and the value it describes. */
|
|
3
|
+
export type DetailListItemType = {
|
|
4
|
+
/** Stable key and test-id segment; the slugified `label` is used when absent. */
|
|
5
|
+
id?: string;
|
|
6
|
+
/** Icon component, or a ready element such as a `Flag`, centred in the row's `FeaturedIcon`. */
|
|
7
|
+
icon: FC<{
|
|
8
|
+
className?: string;
|
|
9
|
+
}> | ReactElement;
|
|
10
|
+
/** What the value is, rendered as the term. */
|
|
11
|
+
label: string;
|
|
12
|
+
/** The value itself: text, or an element such as a `Badge`. */
|
|
13
|
+
value: ReactNode;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=detailList.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detailList.types.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/DetailList/detailList.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEzD,gFAAgF;AAChF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,iFAAiF;IACjF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gGAAgG;IAChG,IAAI,EAAE,EAAE,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,YAAY,CAAC;IAChD,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var FeaturedIcon = require('@flipdish/ui-library/components/atoms/FeaturedIcon');
|
|
5
|
+
var cx = require('@flipdish/ui-library/utilities/cx');
|
|
6
|
+
var testIdUtils = require('@flipdish/ui-library/utilities/testIdUtils');
|
|
7
|
+
|
|
8
|
+
// Row padding equals the icon width plus the gap, so the term and value sit beside the centred icon.
|
|
9
|
+
const sizes = {
|
|
10
|
+
sm: { list: 'gap-4', row: 'pl-11', icon: 'sm', text: 'text-sm' },
|
|
11
|
+
md: { list: 'gap-5', row: 'pl-14', icon: 'md', text: 'text-md' },
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Read-only facts about one record, each row an icon, a label and its value, such as an
|
|
15
|
+
* organisation's type, contact email and country. Use it on summary panels and detail pages
|
|
16
|
+
* where the values are shown, not edited.
|
|
17
|
+
*
|
|
18
|
+
* @summary icon-led label and value rows for one record
|
|
19
|
+
*/
|
|
20
|
+
const DetailList = ({ items, size = 'sm', iconColor = 'brand', iconTheme = 'light', className, 'data-testid': dataTestId, }) => {
|
|
21
|
+
const rootTestId = testIdUtils.useResolvedTestId({ testId: dataTestId, segment: 'detail-list', rootName: 'detail-list' });
|
|
22
|
+
const styles = sizes[size];
|
|
23
|
+
const renderItem = (item) => {
|
|
24
|
+
const key = item.id ?? testIdUtils.slugifyTestId(item.label);
|
|
25
|
+
// The icon lives inside the term and is positioned against the group, so the group holds only `dt` and `dd` as the `dl` content model requires.
|
|
26
|
+
return (jsxRuntime.jsxs("div", { "data-testid": testIdUtils.joinTestId(rootTestId, `item-${key}`), className: cx.cx('relative flex flex-col gap-1', styles.row), children: [jsxRuntime.jsxs("dt", { className: cx.cx('truncate text-primary', styles.text), children: [jsxRuntime.jsx("span", { "aria-hidden": "true", className: "contents", children: jsxRuntime.jsx(FeaturedIcon.FeaturedIcon, { icon: item.icon, size: styles.icon, color: iconColor, theme: iconTheme, className: "absolute top-1/2 left-0 -translate-y-1/2" }) }), item.label] }), jsxRuntime.jsx("dd", { className: cx.cx('truncate font-semibold text-primary', styles.text), children: item.value })] }, key));
|
|
27
|
+
};
|
|
28
|
+
return (jsxRuntime.jsx("dl", { "data-testid": rootTestId, className: cx.cx('flex flex-col', styles.list, className), children: items.map(renderItem) }));
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
exports.DetailList = DetailList;
|
|
32
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/molecules/DetailList/index.tsx"],"sourcesContent":[null],"names":["useResolvedTestId","slugifyTestId","_jsxs","joinTestId","cx","_jsx","FeaturedIcon"],"mappings":";;;;;;;AASA;AACA,MAAM,KAAK,GAAG;AACZ,IAAA,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;AAChE,IAAA,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;CACxD;AAiBV;;;;;;AAMG;AACI,MAAM,UAAU,GAAG,CAAC,EACzB,KAAK,EACL,IAAI,GAAG,IAAI,EACX,SAAS,GAAG,OAAO,EACnB,SAAS,GAAG,OAAO,EACnB,SAAS,EACT,aAAa,EAAE,UAAU,GACT,KAAI;AACpB,IAAA,MAAM,UAAU,GAAGA,6BAAiB,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AAC7G,IAAA,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;AAE1B,IAAA,MAAM,UAAU,GAAG,CAAC,IAAwB,KAAI;AAC9C,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,IAAIC,yBAAa,CAAC,IAAI,CAAC,KAAK,CAAC;;QAGhD,QACEC,wCAA4BC,sBAAU,CAAC,UAAU,EAAE,CAAA,KAAA,EAAQ,GAAG,CAAA,CAAE,CAAC,EAAE,SAAS,EAAEC,KAAE,CAAC,8BAA8B,EAAE,MAAM,CAAC,GAAG,CAAC,EAAA,QAAA,EAAA,CAC1HF,wBAAI,SAAS,EAAEE,KAAE,CAAC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,EAAA,QAAA,EAAA,CAErDC,wCAAkB,MAAM,EAAC,SAAS,EAAC,UAAU,YAC3CA,cAAA,CAACC,yBAAY,EAAA,EACX,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,SAAS,EAChB,SAAS,EAAC,0CAA0C,EAAA,CACpD,EAAA,CACG,EACN,IAAI,CAAC,KAAK,CAAA,EAAA,CACR,EACLD,uBAAI,SAAS,EAAED,KAAE,CAAC,qCAAqC,EAAE,MAAM,CAAC,IAAI,CAAC,EAAA,QAAA,EAAG,IAAI,CAAC,KAAK,GAAM,CAAA,EAAA,EAdhF,GAAG,CAeP;AAEV,IAAA,CAAC;IAED,QACEC,cAAA,CAAA,IAAA,EAAA,EAAA,aAAA,EAAiB,UAAU,EAAE,SAAS,EAAED,KAAE,CAAC,eAAe,EAAE,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,EAAA,QAAA,EAChF,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAA,CACnB;AAET;;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type FeaturedIconProps } from '@flipdish/ui-library/components/atoms/FeaturedIcon';
|
|
2
|
+
import type { DetailListItemType } from './detailList.types';
|
|
3
|
+
export type { DetailListItemType } from './detailList.types';
|
|
4
|
+
export interface DetailListProps {
|
|
5
|
+
/** Rows to show, in order; each `id` (or slugified `label`) must be unique. */
|
|
6
|
+
items: DetailListItemType[];
|
|
7
|
+
/** Icon size and text scale of every row. */
|
|
8
|
+
size?: 'sm' | 'md';
|
|
9
|
+
/** Semantic colour of every row's `FeaturedIcon`. */
|
|
10
|
+
iconColor?: FeaturedIconProps['color'];
|
|
11
|
+
/** Container style of every row's `FeaturedIcon`. */
|
|
12
|
+
iconTheme?: FeaturedIconProps['theme'];
|
|
13
|
+
/** Extra classes merged onto the `<dl>`. */
|
|
14
|
+
className?: string;
|
|
15
|
+
/** Overrides the root `data-testid` (defaults to `fd-detail-list`). Rows derive `<root>--item-<id>` from it. */
|
|
16
|
+
'data-testid'?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Read-only facts about one record, each row an icon, a label and its value, such as an
|
|
20
|
+
* organisation's type, contact email and country. Use it on summary panels and detail pages
|
|
21
|
+
* where the values are shown, not edited.
|
|
22
|
+
*
|
|
23
|
+
* @summary icon-led label and value rows for one record
|
|
24
|
+
*/
|
|
25
|
+
export declare const DetailList: ({ items, size, iconColor, iconTheme, className, "data-testid": dataTestId, }: DetailListProps) => import("react").JSX.Element;
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/DetailList/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,oDAAoD,CAAC;AAG1G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAQ7D,MAAM,WAAW,eAAe;IAC9B,+EAA+E;IAC/E,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,6CAA6C;IAC7C,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,qDAAqD;IACrD,SAAS,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACvC,qDAAqD;IACrD,SAAS,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACvC,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gHAAgH;IAChH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,GAAI,8EAOxB,eAAe,gCAiCjB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { FeaturedIcon } from '@flipdish/ui-library/components/atoms/FeaturedIcon';
|
|
3
|
+
import { cx } from '@flipdish/ui-library/utilities/cx';
|
|
4
|
+
import { useResolvedTestId, slugifyTestId, joinTestId } from '@flipdish/ui-library/utilities/testIdUtils';
|
|
5
|
+
|
|
6
|
+
// Row padding equals the icon width plus the gap, so the term and value sit beside the centred icon.
|
|
7
|
+
const sizes = {
|
|
8
|
+
sm: { list: 'gap-4', row: 'pl-11', icon: 'sm', text: 'text-sm' },
|
|
9
|
+
md: { list: 'gap-5', row: 'pl-14', icon: 'md', text: 'text-md' },
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Read-only facts about one record, each row an icon, a label and its value, such as an
|
|
13
|
+
* organisation's type, contact email and country. Use it on summary panels and detail pages
|
|
14
|
+
* where the values are shown, not edited.
|
|
15
|
+
*
|
|
16
|
+
* @summary icon-led label and value rows for one record
|
|
17
|
+
*/
|
|
18
|
+
const DetailList = ({ items, size = 'sm', iconColor = 'brand', iconTheme = 'light', className, 'data-testid': dataTestId, }) => {
|
|
19
|
+
const rootTestId = useResolvedTestId({ testId: dataTestId, segment: 'detail-list', rootName: 'detail-list' });
|
|
20
|
+
const styles = sizes[size];
|
|
21
|
+
const renderItem = (item) => {
|
|
22
|
+
const key = item.id ?? slugifyTestId(item.label);
|
|
23
|
+
// The icon lives inside the term and is positioned against the group, so the group holds only `dt` and `dd` as the `dl` content model requires.
|
|
24
|
+
return (jsxs("div", { "data-testid": joinTestId(rootTestId, `item-${key}`), className: cx('relative flex flex-col gap-1', styles.row), children: [jsxs("dt", { className: cx('truncate text-primary', styles.text), children: [jsx("span", { "aria-hidden": "true", className: "contents", children: jsx(FeaturedIcon, { icon: item.icon, size: styles.icon, color: iconColor, theme: iconTheme, className: "absolute top-1/2 left-0 -translate-y-1/2" }) }), item.label] }), jsx("dd", { className: cx('truncate font-semibold text-primary', styles.text), children: item.value })] }, key));
|
|
25
|
+
};
|
|
26
|
+
return (jsx("dl", { "data-testid": rootTestId, className: cx('flex flex-col', styles.list, className), children: items.map(renderItem) }));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { DetailList };
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/molecules/DetailList/index.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx"],"mappings":";;;;;AASA;AACA,MAAM,KAAK,GAAG;AACZ,IAAA,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;AAChE,IAAA,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;CACxD;AAiBV;;;;;;AAMG;AACI,MAAM,UAAU,GAAG,CAAC,EACzB,KAAK,EACL,IAAI,GAAG,IAAI,EACX,SAAS,GAAG,OAAO,EACnB,SAAS,GAAG,OAAO,EACnB,SAAS,EACT,aAAa,EAAE,UAAU,GACT,KAAI;AACpB,IAAA,MAAM,UAAU,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AAC7G,IAAA,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;AAE1B,IAAA,MAAM,UAAU,GAAG,CAAC,IAAwB,KAAI;AAC9C,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;;QAGhD,QACEA,6BAA4B,UAAU,CAAC,UAAU,EAAE,CAAA,KAAA,EAAQ,GAAG,CAAA,CAAE,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,8BAA8B,EAAE,MAAM,CAAC,GAAG,CAAC,EAAA,QAAA,EAAA,CAC1HA,aAAI,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,EAAA,QAAA,EAAA,CAErDC,6BAAkB,MAAM,EAAC,SAAS,EAAC,UAAU,YAC3CA,GAAA,CAAC,YAAY,EAAA,EACX,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,SAAS,EAChB,SAAS,EAAC,0CAA0C,EAAA,CACpD,EAAA,CACG,EACN,IAAI,CAAC,KAAK,CAAA,EAAA,CACR,EACLA,YAAI,SAAS,EAAE,EAAE,CAAC,qCAAqC,EAAE,MAAM,CAAC,IAAI,CAAC,EAAA,QAAA,EAAG,IAAI,CAAC,KAAK,GAAM,CAAA,EAAA,EAdhF,GAAG,CAeP;AAEV,IAAA,CAAC;IAED,QACEA,GAAA,CAAA,IAAA,EAAA,EAAA,aAAA,EAAiB,UAAU,EAAE,SAAS,EAAE,EAAE,CAAC,eAAe,EAAE,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,EAAA,QAAA,EAChF,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAA,CACnB;AAET;;"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var Avatar = require('@flipdish/ui-library/components/atoms/Avatar');
|
|
5
|
+
var Checkbox = require('@flipdish/ui-library/components/atoms/Checkbox');
|
|
6
|
+
var RadioButton = require('@flipdish/ui-library/components/atoms/RadioButton');
|
|
7
|
+
var cx = require('@flipdish/ui-library/utilities/cx');
|
|
8
|
+
var testIdUtils = require('@flipdish/ui-library/utilities/testIdUtils');
|
|
9
|
+
var React = require('react');
|
|
10
|
+
var reactAriaComponents = require('react-aria-components');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Radio group where each option is a card with a square logo, title, ID-style subtitle and
|
|
14
|
+
* an optional footer for a link or action. Use to pick a brand, store or other entity by its
|
|
15
|
+
* logo; the footer sits outside the radio, so a link in it never nests inside the control.
|
|
16
|
+
*
|
|
17
|
+
* @summary pick one entity from logo-led cards
|
|
18
|
+
*/
|
|
19
|
+
const RadioGroupAvatarCard = ({ items, size = 'sm', indicator = 'radio', onOptionPress, className, 'data-testid': dataTestId, ...props }) => {
|
|
20
|
+
const rootTestId = testIdUtils.useResolvedTestId({ testId: dataTestId, segment: 'radio-group', rootName: 'radio-group' });
|
|
21
|
+
const Indicator = indicator === 'checkbox' ? Checkbox.CheckboxBase : RadioButton.RadioButtonBase;
|
|
22
|
+
// Ids, not test ids: two groups with the same values on one page must not describe each other's options.
|
|
23
|
+
const groupId = React.useId();
|
|
24
|
+
return (jsxRuntime.jsx(reactAriaComponents.RadioGroup, { ...props, "data-testid": rootTestId, className: (state) => cx.cx('flex flex-col gap-3', typeof className === 'function' ? className(state) : className), children: ({ state, isDisabled: isGroupDisabled }) => items.map((item) => {
|
|
25
|
+
const isSelected = state.selectedValue === item.value;
|
|
26
|
+
const isDisabled = isGroupDisabled || Boolean(item.disabled);
|
|
27
|
+
const optionTestId = testIdUtils.joinTestId(rootTestId, `option-${item.value}`);
|
|
28
|
+
// Slugged: a value with spaces would split `aria-describedby` into several ids.
|
|
29
|
+
const subtitleId = item.subtitle ? `${groupId}-${testIdUtils.slugifyTestId(item.value)}-subtitle` : undefined;
|
|
30
|
+
// The radio is the card's `<label>`; a press in the footer is the footer's own and not an option press. Capture phase,
|
|
31
|
+
// because react-aria stops the radio's click from bubbling. Space on the focused radio fires a native click, so keyboard is covered.
|
|
32
|
+
const handleClickCapture = (event) => {
|
|
33
|
+
if (!isDisabled && event.target instanceof Element && event.target.closest('label'))
|
|
34
|
+
onOptionPress?.(item.value);
|
|
35
|
+
};
|
|
36
|
+
return (
|
|
37
|
+
// The card, not the radio, carries the selected ring so the footer sits inside the same outline.
|
|
38
|
+
jsxRuntime.jsxs("div", { onClickCapture: handleClickCapture, className: cx.cx('flex flex-col rounded-xl bg-primary ring-inset', isSelected ? 'ring-2 ring-brand' : 'ring-1 ring-secondary', isDisabled && 'bg-disabled_subtle ring-disabled_subtle'), children: [jsxRuntime.jsx(reactAriaComponents.Radio, { isDisabled: item.disabled, value: item.value, "aria-label": item.title, "aria-describedby": subtitleId, "data-testid": optionTestId, className: ({ isDisabled, isFocusVisible }) => cx.cx('flex cursor-pointer items-center outline-focus-ring', size === 'md' ? 'gap-4 p-5' : 'gap-3 px-4 py-5', item.footer ? 'rounded-t-xl' : 'rounded-xl', isDisabled && 'cursor-not-allowed', isFocusVisible && 'outline-2 outline-offset-2'), children: ({ isDisabled, isSelected, isFocusVisible }) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Avatar.Avatar, { size: size === 'md' ? 'xl' : 'lg', rounded: false, border: true, src: item.src, alt: "", initials: item.initials, placeholderIcon: item.placeholderIcon }), jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [jsxRuntime.jsx("span", { className: cx.cx('truncate font-semibold text-primary', size === 'md' ? 'text-lg' : 'text-md'), children: item.title }), item.subtitle && (jsxRuntime.jsx("span", { id: subtitleId, className: cx.cx('truncate text-tertiary', size === 'md' ? 'text-md' : 'text-sm'), children: item.subtitle }))] }), jsxRuntime.jsx(Indicator, { size: size, isDisabled: isDisabled, isSelected: isSelected, isFocusVisible: isFocusVisible })] })) }), item.footer && jsxRuntime.jsx("div", { className: "flex justify-end border-t border-secondary px-4 py-3", children: item.footer })] }, item.value));
|
|
39
|
+
}) }));
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
exports.RadioGroupAvatarCard = RadioGroupAvatarCard;
|
|
43
|
+
//# sourceMappingURL=RadioGroupAvatarCard.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RadioGroupAvatarCard.cjs","sources":["../../../../../src/components/molecules/RadioGroup/components/RadioGroupAvatarCard.tsx"],"sourcesContent":[null],"names":["useResolvedTestId","CheckboxBase","RadioButtonBase","useId","_jsx","AriaRadioGroup","cx","joinTestId","slugifyTestId","_jsxs","AriaRadio","_Fragment","Avatar"],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { RadioGroupProps } from 'react-aria-components';
|
|
2
|
+
import type { AvatarCardItemType } from '../radioGroup.types';
|
|
3
|
+
interface RadioGroupAvatarCardProps extends RadioGroupProps {
|
|
4
|
+
/** Avatar, text and indicator size of every option. */
|
|
5
|
+
size?: 'sm' | 'md';
|
|
6
|
+
/** Entities to choose from; each `value` is the option value. */
|
|
7
|
+
items: AvatarCardItemType[];
|
|
8
|
+
/** The selection mark: a radio dot, or the check tile the other flavours use. */
|
|
9
|
+
indicator?: 'radio' | 'checkbox';
|
|
10
|
+
/** Called with the option's value on every press of it, selected or not; `onChange` stays silent for the one already selected. */
|
|
11
|
+
onOptionPress?: (value: string) => void;
|
|
12
|
+
/** Overrides the root `data-testid`. Options derive from it (e.g. `<root>--option-<value>`). */
|
|
13
|
+
'data-testid'?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Radio group where each option is a card with a square logo, title, ID-style subtitle and
|
|
17
|
+
* an optional footer for a link or action. Use to pick a brand, store or other entity by its
|
|
18
|
+
* logo; the footer sits outside the radio, so a link in it never nests inside the control.
|
|
19
|
+
*
|
|
20
|
+
* @summary pick one entity from logo-led cards
|
|
21
|
+
*/
|
|
22
|
+
export declare const RadioGroupAvatarCard: ({ items, size, indicator, onOptionPress, className, "data-testid": dataTestId, ...props }: RadioGroupAvatarCardProps) => import("react").JSX.Element;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=RadioGroupAvatarCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RadioGroupAvatarCard.d.ts","sourceRoot":"","sources":["../../../../../src/components/molecules/RadioGroup/components/RadioGroupAvatarCard.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,UAAU,yBAA0B,SAAQ,eAAe;IACzD,uDAAuD;IACvD,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,iEAAiE;IACjE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACjC,kIAAkI;IAClI,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,gGAAgG;IAChG,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAAI,2FAQlC,yBAAyB,gCAoF3B,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { Avatar } from '@flipdish/ui-library/components/atoms/Avatar';
|
|
3
|
+
import { CheckboxBase } from '@flipdish/ui-library/components/atoms/Checkbox';
|
|
4
|
+
import { RadioButtonBase } from '@flipdish/ui-library/components/atoms/RadioButton';
|
|
5
|
+
import { cx } from '@flipdish/ui-library/utilities/cx';
|
|
6
|
+
import { useResolvedTestId, joinTestId, slugifyTestId } from '@flipdish/ui-library/utilities/testIdUtils';
|
|
7
|
+
import { useId } from 'react';
|
|
8
|
+
import { RadioGroup, Radio } from 'react-aria-components';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Radio group where each option is a card with a square logo, title, ID-style subtitle and
|
|
12
|
+
* an optional footer for a link or action. Use to pick a brand, store or other entity by its
|
|
13
|
+
* logo; the footer sits outside the radio, so a link in it never nests inside the control.
|
|
14
|
+
*
|
|
15
|
+
* @summary pick one entity from logo-led cards
|
|
16
|
+
*/
|
|
17
|
+
const RadioGroupAvatarCard = ({ items, size = 'sm', indicator = 'radio', onOptionPress, className, 'data-testid': dataTestId, ...props }) => {
|
|
18
|
+
const rootTestId = useResolvedTestId({ testId: dataTestId, segment: 'radio-group', rootName: 'radio-group' });
|
|
19
|
+
const Indicator = indicator === 'checkbox' ? CheckboxBase : RadioButtonBase;
|
|
20
|
+
// Ids, not test ids: two groups with the same values on one page must not describe each other's options.
|
|
21
|
+
const groupId = useId();
|
|
22
|
+
return (jsx(RadioGroup, { ...props, "data-testid": rootTestId, className: (state) => cx('flex flex-col gap-3', typeof className === 'function' ? className(state) : className), children: ({ state, isDisabled: isGroupDisabled }) => items.map((item) => {
|
|
23
|
+
const isSelected = state.selectedValue === item.value;
|
|
24
|
+
const isDisabled = isGroupDisabled || Boolean(item.disabled);
|
|
25
|
+
const optionTestId = joinTestId(rootTestId, `option-${item.value}`);
|
|
26
|
+
// Slugged: a value with spaces would split `aria-describedby` into several ids.
|
|
27
|
+
const subtitleId = item.subtitle ? `${groupId}-${slugifyTestId(item.value)}-subtitle` : undefined;
|
|
28
|
+
// The radio is the card's `<label>`; a press in the footer is the footer's own and not an option press. Capture phase,
|
|
29
|
+
// because react-aria stops the radio's click from bubbling. Space on the focused radio fires a native click, so keyboard is covered.
|
|
30
|
+
const handleClickCapture = (event) => {
|
|
31
|
+
if (!isDisabled && event.target instanceof Element && event.target.closest('label'))
|
|
32
|
+
onOptionPress?.(item.value);
|
|
33
|
+
};
|
|
34
|
+
return (
|
|
35
|
+
// The card, not the radio, carries the selected ring so the footer sits inside the same outline.
|
|
36
|
+
jsxs("div", { onClickCapture: handleClickCapture, className: cx('flex flex-col rounded-xl bg-primary ring-inset', isSelected ? 'ring-2 ring-brand' : 'ring-1 ring-secondary', isDisabled && 'bg-disabled_subtle ring-disabled_subtle'), children: [jsx(Radio, { isDisabled: item.disabled, value: item.value, "aria-label": item.title, "aria-describedby": subtitleId, "data-testid": optionTestId, className: ({ isDisabled, isFocusVisible }) => cx('flex cursor-pointer items-center outline-focus-ring', size === 'md' ? 'gap-4 p-5' : 'gap-3 px-4 py-5', item.footer ? 'rounded-t-xl' : 'rounded-xl', isDisabled && 'cursor-not-allowed', isFocusVisible && 'outline-2 outline-offset-2'), children: ({ isDisabled, isSelected, isFocusVisible }) => (jsxs(Fragment, { children: [jsx(Avatar, { size: size === 'md' ? 'xl' : 'lg', rounded: false, border: true, src: item.src, alt: "", initials: item.initials, placeholderIcon: item.placeholderIcon }), jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [jsx("span", { className: cx('truncate font-semibold text-primary', size === 'md' ? 'text-lg' : 'text-md'), children: item.title }), item.subtitle && (jsx("span", { id: subtitleId, className: cx('truncate text-tertiary', size === 'md' ? 'text-md' : 'text-sm'), children: item.subtitle }))] }), jsx(Indicator, { size: size, isDisabled: isDisabled, isSelected: isSelected, isFocusVisible: isFocusVisible })] })) }), item.footer && jsx("div", { className: "flex justify-end border-t border-secondary px-4 py-3", children: item.footer })] }, item.value));
|
|
37
|
+
}) }));
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { RadioGroupAvatarCard };
|
|
41
|
+
//# sourceMappingURL=RadioGroupAvatarCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RadioGroupAvatarCard.js","sources":["../../../../../src/components/molecules/RadioGroup/components/RadioGroupAvatarCard.tsx"],"sourcesContent":[null],"names":["_jsx","AriaRadioGroup","_jsxs","AriaRadio","_Fragment"],"mappings":"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"}
|