@activecollab/components 2.0.423 → 2.0.425

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/cjs/components/Media/Media.js +45 -4
  2. package/dist/cjs/components/Media/Media.js.map +1 -1
  3. package/dist/cjs/components/Media/Styles.js +4 -1
  4. package/dist/cjs/components/Media/Styles.js.map +1 -1
  5. package/dist/cjs/components/PortableText/renderers.js +8 -2
  6. package/dist/cjs/components/PortableText/renderers.js.map +1 -1
  7. package/dist/cjs/components/PortableText/types.js.map +1 -1
  8. package/dist/cjs/presentation/shared/portfolioDetails.js +1 -1
  9. package/dist/cjs/presentation/shared/portfolioDetails.js.map +1 -1
  10. package/dist/esm/components/Media/Media.d.ts +9 -0
  11. package/dist/esm/components/Media/Media.d.ts.map +1 -1
  12. package/dist/esm/components/Media/Media.js +44 -3
  13. package/dist/esm/components/Media/Media.js.map +1 -1
  14. package/dist/esm/components/Media/Styles.d.ts +1 -0
  15. package/dist/esm/components/Media/Styles.d.ts.map +1 -1
  16. package/dist/esm/components/Media/Styles.js +4 -1
  17. package/dist/esm/components/Media/Styles.js.map +1 -1
  18. package/dist/esm/components/PortableText/renderers.d.ts.map +1 -1
  19. package/dist/esm/components/PortableText/renderers.js +8 -2
  20. package/dist/esm/components/PortableText/renderers.js.map +1 -1
  21. package/dist/esm/components/PortableText/types.d.ts +16 -0
  22. package/dist/esm/components/PortableText/types.d.ts.map +1 -1
  23. package/dist/esm/components/PortableText/types.js.map +1 -1
  24. package/dist/esm/presentation/shared/portfolioDetails.js +1 -1
  25. package/dist/esm/presentation/shared/portfolioDetails.js.map +1 -1
  26. package/dist/index.js +57 -6
  27. package/dist/index.js.map +1 -1
  28. package/dist/index.min.js +1 -1
  29. package/dist/index.min.js.map +1 -1
  30. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"portfolioDetails.js","names":["React","useEffect","useMemo","useState","styled","Button","Dialog","IconButton","SortGeneralIcon","Input","Label","RadioGroup","Select","SelectTrigger","DEFAULT_PORTFOLIO_FORM_VALUES","type","name","context","undefined","projectIds","groupBy","visibility","LEADERS_LIST","short","CATEGORIES","CLIENTS","PICKER_PROJECTS","id","client","category","label","leader","favorite","GROUP_BY_OPTIONS","projectOptionId","project","sampleProjectOptionIds","count","slice","Math","max","map","toProjectOptions","projects","sort","a","b","localeCompare","groupPickerProjects","filter","other","groups","length","push","options","field","without","buckets","Map","forEach","_buckets$get","key","has","set","get","Array","from","entries","_ref","PORTFOLIO_TYPES","title","description","VISIBILITY_OPTIONS","contextFieldLabel","leaderShortName","_LEADERS_LIST$find$sh","_LEADERS_LIST$find","find","defaultPortfolioName","isPortfolioDetailsValid","values","trim","Boolean","ProjectsGroupBy","_ref2","selected","onChange","createElement","keepSameOptionsOrder","disableSearch","disabledInternalSort","forceCloseMenu","position","value","target","variant","ProjectsPicker","_ref3","onGroupBy","invalid","triggerText","noResultText","endAdornment","className","typographyProps","color","ContextPicker","_ref4","placeholder","next","String","StyledDetailsForm","div","withConfig","displayName","componentId","PortfolioDetailsFields","_ref5","onName","onContext","onProjects","onVisibility","showErrors","nameInvalid","pickerInvalid","htmlFor","event","option","EditPortfolioDialog","_ref6","open","initialValues","onClose","onSave","_useState","setValues","_useState2","setShowErrors","patch","current","_extends","handleSave","disableCloseOnEsc","Title","ContentDivider","Content","Actions","style","marginRight","onClick"],"sources":["../../../../src/presentation/shared/portfolioDetails.tsx"],"sourcesContent":["import React, { ReactElement, useEffect, useMemo, useState } from \"react\";\n\nimport styled from \"styled-components\";\n\nimport { Button } from \"../../components/Button\";\nimport { Dialog } from \"../../components/Dialog\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { SortGeneralIcon } from \"../../components/Icons\";\nimport { Input } from \"../../components/Input\";\nimport { Label } from \"../../components/Label\";\nimport { RadioGroup } from \"../../components/RadioGroup\";\nimport { Select } from \"../../components/Select\";\nimport { SelectTrigger } from \"../../components/SelectTrigger\";\n\n/*\n Portfolio details form — the shared \"step 2\" of the Create Portfolio wizard,\n reused verbatim as the Edit Portfolio dialog.\n\n This mirrors a pattern used across the app: the fields that make up the final\n step of a creation wizard are the same fields shown, later, when the object is\n edited. So the form body (name, the type's picker, visibility) and its\n validation live here once, and two consumers render it:\n\n - The Create Portfolio wizard (PortfoliosList.stories.tsx) renders\n <PortfolioDetailsFields> inside its step-2 <Dialog.Content>, with a\n \"Create Portfolio\" action.\n - <EditPortfolioDialog> (opened from PortfolioOptionsMenu's Edit item)\n renders the SAME <PortfolioDetailsFields> inside a standalone <Dialog>,\n with a \"Save Changes\" action.\n\n Both use isPortfolioDetailsValid() and the same always-enabled-submit,\n outline-on-submit validation rule.\n*/\n\n/* ------------------------------------------------------------------ */\n/* Domain types */\n/* ------------------------------------------------------------------ */\n\n/** How a portfolio decides its members (two kinds, three context types). */\nexport type PortfolioKind = \"custom\" | \"category\" | \"client\" | \"leader\";\n\nexport type PortfolioVisibility = \"everyone\" | \"me\";\n\n/** Grouping of the projects multi-select — matches Invite-to-Projects. */\nexport type GroupBy =\n | \"favorites\"\n | \"labels\"\n | \"companies\"\n | \"categories\"\n | \"leaders\";\n\n/** The editable shape shared by create step 2 and the edit dialog. */\nexport interface PortfolioFormValues {\n type: PortfolioKind;\n name: string;\n /** For context portfolios: the chosen category / client / leader. */\n context?: string;\n /** For custom portfolios: the hand-picked project option ids. */\n projectIds: string[];\n groupBy: GroupBy;\n visibility: PortfolioVisibility;\n}\n\n/** A blank custom portfolio — the fallback seed for the edit dialog. */\nexport const DEFAULT_PORTFOLIO_FORM_VALUES: PortfolioFormValues = {\n type: \"custom\",\n name: \"\",\n context: undefined,\n projectIds: [],\n groupBy: \"favorites\",\n visibility: \"everyone\",\n};\n\n/* ------------------------------------------------------------------ */\n/* Pickers' mock data */\n/* ------------------------------------------------------------------ */\n\nexport interface PickerLeader {\n name: string;\n /** Short \"Firstname L.\" form used in the default portfolio name. */\n short: string;\n}\n\nexport const LEADERS_LIST: PickerLeader[] = [\n { name: \"Theo Brandt\", short: \"Theo B.\" },\n { name: \"Isabel Cortez\", short: \"Isabel C.\" },\n { name: \"Grace Bauer\", short: \"Grace B.\" },\n { name: \"Noah Mercer\", short: \"Noah M.\" },\n];\n\nexport const CATEGORIES = [\n \"Brand & Identity\",\n \"Web & Product\",\n \"Marketing\",\n \"Internal Ops\",\n];\n\nexport const CLIENTS = [\n \"Aperture Studio\",\n \"Orbit Telecom\",\n \"Northwind Traders\",\n \"Meridian Health\",\n];\n\ninterface PickerProject {\n id: number;\n name: string;\n client: string;\n category: string;\n label: string;\n leader: string;\n favorite: boolean;\n}\n\nconst PICKER_PROJECTS: PickerProject[] = [\n {\n id: 1,\n name: \"Website Redesign\",\n client: \"Aperture Studio\",\n category: \"Web & Product\",\n label: \"Design\",\n leader: \"Theo Brandt\",\n favorite: true,\n },\n {\n id: 2,\n name: \"Brand Refresh\",\n client: \"Aperture Studio\",\n category: \"Brand & Identity\",\n label: \"Design\",\n leader: \"Isabel Cortez\",\n favorite: true,\n },\n {\n id: 3,\n name: \"Mobile App\",\n client: \"Orbit Telecom\",\n category: \"Web & Product\",\n label: \"Build\",\n leader: \"Grace Bauer\",\n favorite: false,\n },\n {\n id: 4,\n name: \"Q3 Campaign\",\n client: \"Orbit Telecom\",\n category: \"Marketing\",\n label: \"Campaign\",\n leader: \"Noah Mercer\",\n favorite: true,\n },\n {\n id: 5,\n name: \"Internal Wiki\",\n client: \"\",\n category: \"Internal Ops\",\n label: \"\",\n leader: \"Theo Brandt\",\n favorite: false,\n },\n {\n id: 6,\n name: \"Packaging System\",\n client: \"Northwind Traders\",\n category: \"Brand & Identity\",\n label: \"Design\",\n leader: \"Isabel Cortez\",\n favorite: false,\n },\n {\n id: 7,\n name: \"Support Portal\",\n client: \"Meridian Health\",\n category: \"Web & Product\",\n label: \"Build\",\n leader: \"Grace Bauer\",\n favorite: false,\n },\n {\n id: 8,\n name: \"Annual Report\",\n client: \"Northwind Traders\",\n category: \"Marketing\",\n label: \"Campaign\",\n leader: \"Noah Mercer\",\n favorite: true,\n },\n];\n\n/* Group-by options and default match the Invite-to-Projects picker exactly. */\nconst GROUP_BY_OPTIONS: { id: GroupBy; name: string }[] = [\n { id: \"favorites\", name: \"Favorites\" },\n { id: \"labels\", name: \"Label\" },\n { id: \"companies\", name: \"Client\" },\n { id: \"categories\", name: \"Category\" },\n { id: \"leaders\", name: \"Project Leader\" },\n];\n\ninterface ProjectOption {\n id: string;\n name: string;\n}\ninterface ProjectOptionGroup {\n id: string;\n name: string;\n options: ProjectOption[];\n}\n\nconst projectOptionId = (project: PickerProject): string => `p${project.id}`;\n\n/** A small deterministic set of project option ids — seeds a custom\n portfolio's edit dialog so the picker reads as an existing selection. */\nexport const sampleProjectOptionIds = (count: number): string[] =>\n PICKER_PROJECTS.slice(0, Math.max(0, count)).map(projectOptionId);\n\nconst toProjectOptions = (projects: PickerProject[]): ProjectOption[] =>\n projects\n .map((project) => ({ id: projectOptionId(project), name: project.name }))\n .sort((a, b) => a.name.localeCompare(b.name));\n\n/* Build the grouped option tree the Select expects. Alphabetical rows and\n groups; the \"Without ...\" / \"Other\" bucket sits last; the Favorites grouping\n collapses to a flat list when it is the only group (as the app's does). */\nconst groupPickerProjects = (\n groupBy: GroupBy\n): ProjectOption[] | ProjectOptionGroup[] => {\n if (groupBy === \"favorites\") {\n const favorite = PICKER_PROJECTS.filter((project) => project.favorite);\n const other = PICKER_PROJECTS.filter((project) => !project.favorite);\n const groups: ProjectOptionGroup[] = [];\n if (favorite.length) {\n groups.push({\n id: \"g-fav\",\n name: \"Favorite\",\n options: toProjectOptions(favorite),\n });\n }\n if (other.length) {\n groups.push({\n id: \"g-other\",\n name: \"Other\",\n options: toProjectOptions(other),\n });\n }\n return groups.length === 1 ? groups[0].options : groups;\n }\n\n const field: keyof PickerProject =\n groupBy === \"labels\"\n ? \"label\"\n : groupBy === \"companies\"\n ? \"client\"\n : groupBy === \"categories\"\n ? \"category\"\n : \"leader\";\n const without =\n groupBy === \"labels\"\n ? \"Without Label\"\n : groupBy === \"companies\"\n ? \"Without Client\"\n : groupBy === \"categories\"\n ? \"Without Category\"\n : \"Without Leader\";\n\n const buckets = new Map<string, PickerProject[]>();\n PICKER_PROJECTS.forEach((project) => {\n const key = (project[field] as string) || without;\n if (!buckets.has(key)) {\n buckets.set(key, []);\n }\n buckets.get(key)?.push(project);\n });\n\n return Array.from(buckets.entries())\n .map(([name, projects]) => ({\n id: `g-${name}`,\n name,\n options: toProjectOptions(projects),\n }))\n .sort((a, b) =>\n a.name === without\n ? 1\n : b.name === without\n ? -1\n : a.name.localeCompare(b.name)\n );\n};\n\n/* ------------------------------------------------------------------ */\n/* Type + visibility option copy */\n/* ------------------------------------------------------------------ */\n\nexport const PORTFOLIO_TYPES: {\n id: PortfolioKind;\n title: string;\n description: string;\n}[] = [\n {\n id: \"custom\",\n title: \"Custom Portfolio\",\n description: \"The projects you pick by hand. Nothing joins automatically.\",\n },\n {\n id: \"client\",\n title: \"Client Portfolio\",\n description:\n \"All projects for a client company. New ones join automatically.\",\n },\n {\n id: \"leader\",\n title: \"Project Leader Portfolio\",\n description: \"All projects led by a person. New ones join automatically.\",\n },\n {\n id: \"category\",\n title: \"Category Portfolio\",\n description:\n \"All projects in a project category. New ones join automatically.\",\n },\n];\n\nexport const VISIBILITY_OPTIONS: {\n id: PortfolioVisibility;\n title: string;\n description: string;\n}[] = [\n {\n id: \"everyone\",\n title: \"Visible to Everyone\",\n description:\n \"Anyone who can use portfolios sees this one. They still only see the projects they already have access to.\",\n },\n {\n id: \"me\",\n title: \"Visible Only to Me\",\n description: \"Nobody else sees this portfolio.\",\n },\n];\n\nexport const contextFieldLabel = (type: PortfolioKind): string =>\n type === \"custom\"\n ? \"Projects\"\n : type === \"category\"\n ? \"Category\"\n : type === \"client\"\n ? \"Client\"\n : \"Project leader\";\n\nexport const leaderShortName = (name: string): string =>\n LEADERS_LIST.find((leader) => leader.name === name)?.short ?? name;\n\n/* Default names: \"{Category} Projects\", \"{Client} Projects\", \"Lead by {N.}\". */\nexport const defaultPortfolioName = (\n type: PortfolioKind,\n context: string\n): string => {\n if (!context) return \"\";\n if (type === \"category\" || type === \"client\") return `${context} Projects`;\n if (type === \"leader\") return `Lead by ${leaderShortName(context)}`;\n return \"\";\n};\n\n/* ------------------------------------------------------------------ */\n/* Validation (shared by create step 2 and the edit dialog) */\n/* ------------------------------------------------------------------ */\n\n/** Name is required; a custom portfolio needs at least one project, a context\n portfolio needs its context chosen. Same rule for create and edit. */\nexport const isPortfolioDetailsValid = (values: PortfolioFormValues): boolean =>\n values.name.trim().length > 0 &&\n (values.type === \"custom\"\n ? values.projectIds.length > 0\n : Boolean(values.context));\n\n/* ------------------------------------------------------------------ */\n/* Pickers */\n/* ------------------------------------------------------------------ */\n\n/* Group-by control: the SortGeneralIcon button the Invite-to-Projects picker\n shows as the search bar's right-side adornment. Controls grouping, not sort. */\nconst ProjectsGroupBy = ({\n selected,\n onChange,\n}: {\n selected: GroupBy;\n onChange: (groupBy: GroupBy) => void;\n}): ReactElement => (\n <Select\n keepSameOptionsOrder\n disableSearch\n disabledInternalSort\n forceCloseMenu\n position=\"bottom-end\"\n selected={selected}\n onChange={(value) => onChange(value as GroupBy)}\n options={GROUP_BY_OPTIONS}\n target={\n <IconButton type=\"button\" variant=\"text gray\">\n <SortGeneralIcon />\n </IconButton>\n }\n />\n);\n\nconst ProjectsPicker = ({\n selected,\n onChange,\n groupBy,\n onGroupBy,\n invalid,\n}: {\n selected: string[];\n onChange: (ids: string[]) => void;\n groupBy: GroupBy;\n onGroupBy: (groupBy: GroupBy) => void;\n invalid?: boolean;\n}): ReactElement => {\n const options = useMemo(() => groupPickerProjects(groupBy), [groupBy]);\n const count = selected.length;\n const triggerText =\n count === 0\n ? \"Choose projects\"\n : count === 1\n ? \"1 project selected\"\n : `${count} projects selected`;\n return (\n <Select\n type=\"multiple\"\n options={options}\n selected={selected}\n onChange={(value) => onChange(value as string[])}\n noResultText=\"No results\"\n endAdornment={<ProjectsGroupBy selected={groupBy} onChange={onGroupBy} />}\n target={\n <SelectTrigger\n id=\"pf-projects\"\n className=\"pf-trigger\"\n invalid={invalid}\n typographyProps={{ color: count > 0 ? \"primary\" : \"quaternary\" }}\n >\n {triggerText}\n </SelectTrigger>\n }\n />\n );\n};\n\nconst ContextPicker = ({\n type,\n value,\n onChange,\n invalid,\n}: {\n type: PortfolioKind;\n value?: string;\n onChange: (value: string) => void;\n invalid?: boolean;\n}): ReactElement => {\n const options =\n type === \"category\"\n ? CATEGORIES.map((name) => ({ id: name, name }))\n : type === \"client\"\n ? CLIENTS.map((name) => ({ id: name, name }))\n : LEADERS_LIST.map((leader) => ({ id: leader.name, name: leader.name }));\n const placeholder =\n type === \"category\"\n ? \"Choose a category\"\n : type === \"client\"\n ? \"Choose a client\"\n : \"Choose a project leader\";\n return (\n <Select\n forceCloseMenu\n options={options}\n selected={value ?? \"\"}\n onChange={(next) => onChange(String(next))}\n target={\n <SelectTrigger\n id=\"pf-context\"\n className=\"pf-trigger\"\n invalid={invalid}\n typographyProps={{ color: value ? \"primary\" : \"quaternary\" }}\n >\n {value ?? placeholder}\n </SelectTrigger>\n }\n />\n );\n};\n\n/* ------------------------------------------------------------------ */\n/* The reusable form body */\n/* ------------------------------------------------------------------ */\n\nconst StyledDetailsForm = styled.div`\n display: flex;\n flex-direction: column;\n gap: 24px;\n\n .field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n /* DS form controls are fixed-width (Input 360px, SelectTrigger 300px); let\n them fill the dialog column instead. */\n .field .c-input-wrapper {\n width: 100%;\n }\n\n .field .pf-trigger {\n width: 100%;\n }\n`;\n\nexport interface PortfolioDetailsFieldsProps {\n values: PortfolioFormValues;\n onName: (value: string) => void;\n onContext: (value: string) => void;\n onProjects: (ids: string[]) => void;\n onGroupBy: (groupBy: GroupBy) => void;\n onVisibility: (value: PortfolioVisibility) => void;\n /* Form pattern (propagating through the app): the submit button is ALWAYS\n enabled. On submit the consumer flips showErrors; each field then outlines\n itself (aria-invalid) while it is invalid, and clears once it becomes\n valid. No field disables submit. */\n showErrors: boolean;\n}\n\n/** Name + the type's picker + visibility. No Dialog wrappers and no action\n button — the consumer (create step or edit dialog) supplies those. */\nexport const PortfolioDetailsFields = ({\n values,\n onName,\n onContext,\n onProjects,\n onGroupBy,\n onVisibility,\n showErrors,\n}: PortfolioDetailsFieldsProps): ReactElement => {\n const { type, name, context, projectIds, groupBy, visibility } = values;\n const nameInvalid = showErrors && name.trim().length === 0;\n const pickerInvalid =\n showErrors && (type === \"custom\" ? projectIds.length === 0 : !context);\n\n return (\n <StyledDetailsForm>\n <div className=\"field\">\n <Label htmlFor=\"pf-name\">Name</Label>\n <Input\n id=\"pf-name\"\n value={name}\n placeholder=\"Portfolio name\"\n invalid={nameInvalid}\n onChange={(event) => onName(event.target.value)}\n />\n </div>\n <div className=\"field\">\n <Label htmlFor={type === \"custom\" ? \"pf-projects\" : \"pf-context\"}>\n {contextFieldLabel(type)}\n </Label>\n {type === \"custom\" ? (\n <ProjectsPicker\n selected={projectIds}\n onChange={onProjects}\n groupBy={groupBy}\n onGroupBy={onGroupBy}\n invalid={pickerInvalid}\n />\n ) : (\n <ContextPicker\n type={type}\n value={context}\n onChange={onContext}\n invalid={pickerInvalid}\n />\n )}\n </div>\n <div className=\"field\">\n <RadioGroup\n label=\"Visibility\"\n variant=\"plain\"\n value={visibility}\n onChange={(value) => onVisibility(value as PortfolioVisibility)}\n options={VISIBILITY_OPTIONS.map((option) => ({\n id: option.id,\n name: option.title,\n description: option.description,\n }))}\n />\n </div>\n </StyledDetailsForm>\n );\n};\n\nPortfolioDetailsFields.displayName = \"PortfolioDetailsFields\";\n\n/* ------------------------------------------------------------------ */\n/* Edit Portfolio dialog — the create wizard's step 2, on its own */\n/* ------------------------------------------------------------------ */\n\nexport interface EditPortfolioDialogProps {\n open: boolean;\n /** The portfolio's current values; the dialog seeds itself from these on\n open, so Cancel discards edits and Save commits them. */\n initialValues: PortfolioFormValues;\n onClose: () => void;\n onSave?: (values: PortfolioFormValues) => void;\n}\n\n/*\n Same fields, same validation as create step 2. The type is fixed to the\n portfolio's kind (edit changes the details, not the kind), so there is no\n type radio here — only the name, the type's picker, and visibility.\n*/\nexport const EditPortfolioDialog = ({\n open,\n initialValues,\n onClose,\n onSave,\n}: EditPortfolioDialogProps): ReactElement => {\n const [values, setValues] = useState<PortfolioFormValues>(initialValues);\n const [showErrors, setShowErrors] = useState(false);\n\n /* Re-seed from the portfolio each time the dialog opens. */\n useEffect(() => {\n if (open) {\n setValues(initialValues);\n setShowErrors(false);\n }\n // Seed on open only — initialValues is read at that moment by design.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n const patch = (next: Partial<PortfolioFormValues>): void =>\n setValues((current) => ({ ...current, ...next }));\n\n const handleSave = (): void => {\n if (!isPortfolioDetailsValid(values)) {\n setShowErrors(true);\n return;\n }\n onSave?.(values);\n onClose();\n };\n\n return (\n <Dialog open={open} onClose={onClose} disableCloseOnEsc>\n <Dialog.Title>Edit Portfolio</Dialog.Title>\n <Dialog.ContentDivider />\n <Dialog.Content>\n <PortfolioDetailsFields\n values={values}\n onName={(name) => patch({ name })}\n onContext={(context) => patch({ context })}\n onProjects={(projectIds) => patch({ projectIds })}\n onGroupBy={(groupBy) => patch({ groupBy })}\n onVisibility={(visibility) => patch({ visibility })}\n showErrors={showErrors}\n />\n </Dialog.Content>\n <Dialog.ContentDivider />\n <Dialog.Actions>\n <Button\n variant=\"primary\"\n style={{ marginRight: \"12px\" }}\n onClick={handleSave}\n >\n Save Changes\n </Button>\n <Button variant=\"secondary\" data-action=\"cancel\" onClick={onClose}>\n Cancel\n </Button>\n </Dialog.Actions>\n </Dialog>\n );\n};\n\nEditPortfolioDialog.displayName = \"EditPortfolioDialog\";\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"portfolioDetails.js","names":["React","useEffect","useMemo","useState","styled","Button","Dialog","IconButton","SortGeneralIcon","Input","Label","RadioGroup","Select","SelectTrigger","DEFAULT_PORTFOLIO_FORM_VALUES","type","name","context","undefined","projectIds","groupBy","visibility","LEADERS_LIST","short","CATEGORIES","CLIENTS","PICKER_PROJECTS","id","client","category","label","leader","favorite","GROUP_BY_OPTIONS","projectOptionId","project","sampleProjectOptionIds","count","slice","Math","max","map","toProjectOptions","projects","sort","a","b","localeCompare","groupPickerProjects","filter","other","groups","length","push","options","field","without","buckets","Map","forEach","_buckets$get","key","has","set","get","Array","from","entries","_ref","PORTFOLIO_TYPES","title","description","VISIBILITY_OPTIONS","contextFieldLabel","leaderShortName","_LEADERS_LIST$find$sh","_LEADERS_LIST$find","find","defaultPortfolioName","isPortfolioDetailsValid","values","trim","Boolean","ProjectsGroupBy","_ref2","selected","onChange","createElement","keepSameOptionsOrder","disableSearch","disabledInternalSort","forceCloseMenu","position","value","target","variant","ProjectsPicker","_ref3","onGroupBy","invalid","triggerText","noResultText","endAdornment","className","typographyProps","color","ContextPicker","_ref4","placeholder","next","String","StyledDetailsForm","div","withConfig","displayName","componentId","PortfolioDetailsFields","_ref5","onName","onContext","onProjects","onVisibility","showErrors","nameInvalid","pickerInvalid","htmlFor","event","option","EditPortfolioDialog","_ref6","open","initialValues","onClose","onSave","_useState","setValues","_useState2","setShowErrors","patch","current","_extends","handleSave","disableCloseOnEsc","Title","ContentDivider","Content","Actions","style","marginRight","onClick"],"sources":["../../../../src/presentation/shared/portfolioDetails.tsx"],"sourcesContent":["import React, { ReactElement, useEffect, useMemo, useState } from \"react\";\n\nimport styled from \"styled-components\";\n\nimport { Button } from \"../../components/Button\";\nimport { Dialog } from \"../../components/Dialog\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { SortGeneralIcon } from \"../../components/Icons\";\nimport { Input } from \"../../components/Input\";\nimport { Label } from \"../../components/Label\";\nimport { RadioGroup } from \"../../components/RadioGroup\";\nimport { Select } from \"../../components/Select\";\nimport { SelectTrigger } from \"../../components/SelectTrigger\";\n\n/*\n Portfolio details form — the shared \"step 2\" of the Create Portfolio wizard,\n reused verbatim as the Edit Portfolio dialog.\n\n This mirrors a pattern used across the app: the fields that make up the final\n step of a creation wizard are the same fields shown, later, when the object is\n edited. So the form body (name, the type's picker, visibility) and its\n validation live here once, and two consumers render it:\n\n - The Create Portfolio wizard (PortfoliosList.stories.tsx) renders\n <PortfolioDetailsFields> inside its step-2 <Dialog.Content>, with a\n \"Create Portfolio\" action.\n - <EditPortfolioDialog> (opened from PortfolioOptionsMenu's Edit item)\n renders the SAME <PortfolioDetailsFields> inside a standalone <Dialog>,\n with a \"Save Changes\" action.\n\n Both use isPortfolioDetailsValid() and the same always-enabled-submit,\n outline-on-submit validation rule.\n*/\n\n/* ------------------------------------------------------------------ */\n/* Domain types */\n/* ------------------------------------------------------------------ */\n\n/** How a portfolio decides its members (two kinds, three context types). */\nexport type PortfolioKind = \"custom\" | \"category\" | \"client\" | \"leader\";\n\nexport type PortfolioVisibility = \"everyone\" | \"me\";\n\n/** Grouping of the projects multi-select — matches Invite-to-Projects. */\nexport type GroupBy =\n | \"favorites\"\n | \"labels\"\n | \"companies\"\n | \"categories\"\n | \"leaders\";\n\n/** The editable shape shared by create step 2 and the edit dialog. */\nexport interface PortfolioFormValues {\n type: PortfolioKind;\n name: string;\n /** For context portfolios: the chosen category / client / leader. */\n context?: string;\n /** For custom portfolios: the hand-picked project option ids. */\n projectIds: string[];\n groupBy: GroupBy;\n visibility: PortfolioVisibility;\n}\n\n/** A blank custom portfolio — the fallback seed for the edit dialog. */\nexport const DEFAULT_PORTFOLIO_FORM_VALUES: PortfolioFormValues = {\n type: \"custom\",\n name: \"\",\n context: undefined,\n projectIds: [],\n groupBy: \"favorites\",\n visibility: \"everyone\",\n};\n\n/* ------------------------------------------------------------------ */\n/* Pickers' mock data */\n/* ------------------------------------------------------------------ */\n\nexport interface PickerLeader {\n name: string;\n /** Short \"Firstname L.\" form used in the default portfolio name. */\n short: string;\n}\n\nexport const LEADERS_LIST: PickerLeader[] = [\n { name: \"Theo Brandt\", short: \"Theo B.\" },\n { name: \"Isabel Cortez\", short: \"Isabel C.\" },\n { name: \"Grace Bauer\", short: \"Grace B.\" },\n { name: \"Noah Mercer\", short: \"Noah M.\" },\n];\n\nexport const CATEGORIES = [\n \"Brand & Identity\",\n \"Web & Product\",\n \"Marketing\",\n \"Internal Ops\",\n];\n\nexport const CLIENTS = [\n \"Aperture Studio\",\n \"Orbit Telecom\",\n \"Northwind Traders\",\n \"Meridian Health\",\n];\n\ninterface PickerProject {\n id: number;\n name: string;\n client: string;\n category: string;\n label: string;\n leader: string;\n favorite: boolean;\n}\n\nconst PICKER_PROJECTS: PickerProject[] = [\n {\n id: 1,\n name: \"Website Redesign\",\n client: \"Aperture Studio\",\n category: \"Web & Product\",\n label: \"Design\",\n leader: \"Theo Brandt\",\n favorite: true,\n },\n {\n id: 2,\n name: \"Brand Refresh\",\n client: \"Aperture Studio\",\n category: \"Brand & Identity\",\n label: \"Design\",\n leader: \"Isabel Cortez\",\n favorite: true,\n },\n {\n id: 3,\n name: \"Mobile App\",\n client: \"Orbit Telecom\",\n category: \"Web & Product\",\n label: \"Build\",\n leader: \"Grace Bauer\",\n favorite: false,\n },\n {\n id: 4,\n name: \"Q3 Campaign\",\n client: \"Orbit Telecom\",\n category: \"Marketing\",\n label: \"Campaign\",\n leader: \"Noah Mercer\",\n favorite: true,\n },\n {\n id: 5,\n name: \"Internal Wiki\",\n client: \"\",\n category: \"Internal Ops\",\n label: \"\",\n leader: \"Theo Brandt\",\n favorite: false,\n },\n {\n id: 6,\n name: \"Packaging System\",\n client: \"Northwind Traders\",\n category: \"Brand & Identity\",\n label: \"Design\",\n leader: \"Isabel Cortez\",\n favorite: false,\n },\n {\n id: 7,\n name: \"Support Portal\",\n client: \"Meridian Health\",\n category: \"Web & Product\",\n label: \"Build\",\n leader: \"Grace Bauer\",\n favorite: false,\n },\n {\n id: 8,\n name: \"Annual Report\",\n client: \"Northwind Traders\",\n category: \"Marketing\",\n label: \"Campaign\",\n leader: \"Noah Mercer\",\n favorite: true,\n },\n];\n\n/* Group-by options and default match the Invite-to-Projects picker exactly. */\nconst GROUP_BY_OPTIONS: { id: GroupBy; name: string }[] = [\n { id: \"favorites\", name: \"Favorites\" },\n { id: \"labels\", name: \"Label\" },\n { id: \"companies\", name: \"Client\" },\n { id: \"categories\", name: \"Category\" },\n { id: \"leaders\", name: \"Project Leader\" },\n];\n\ninterface ProjectOption {\n id: string;\n name: string;\n}\ninterface ProjectOptionGroup {\n id: string;\n name: string;\n options: ProjectOption[];\n}\n\nconst projectOptionId = (project: PickerProject): string => `p${project.id}`;\n\n/** A small deterministic set of project option ids — seeds a custom\n portfolio's edit dialog so the picker reads as an existing selection. */\nexport const sampleProjectOptionIds = (count: number): string[] =>\n PICKER_PROJECTS.slice(0, Math.max(0, count)).map(projectOptionId);\n\nconst toProjectOptions = (projects: PickerProject[]): ProjectOption[] =>\n projects\n .map((project) => ({ id: projectOptionId(project), name: project.name }))\n .sort((a, b) => a.name.localeCompare(b.name));\n\n/* Build the grouped option tree the Select expects. Alphabetical rows and\n groups; the \"Without ...\" / \"Other\" bucket sits last; the Favorites grouping\n collapses to a flat list when it is the only group (as the app's does). */\nconst groupPickerProjects = (\n groupBy: GroupBy\n): ProjectOption[] | ProjectOptionGroup[] => {\n if (groupBy === \"favorites\") {\n const favorite = PICKER_PROJECTS.filter((project) => project.favorite);\n const other = PICKER_PROJECTS.filter((project) => !project.favorite);\n const groups: ProjectOptionGroup[] = [];\n if (favorite.length) {\n groups.push({\n id: \"g-fav\",\n name: \"Favorite\",\n options: toProjectOptions(favorite),\n });\n }\n if (other.length) {\n groups.push({\n id: \"g-other\",\n name: \"Other\",\n options: toProjectOptions(other),\n });\n }\n return groups.length === 1 ? groups[0].options : groups;\n }\n\n const field: keyof PickerProject =\n groupBy === \"labels\"\n ? \"label\"\n : groupBy === \"companies\"\n ? \"client\"\n : groupBy === \"categories\"\n ? \"category\"\n : \"leader\";\n const without =\n groupBy === \"labels\"\n ? \"Without Label\"\n : groupBy === \"companies\"\n ? \"Without Client\"\n : groupBy === \"categories\"\n ? \"Without Category\"\n : \"Without Leader\";\n\n const buckets = new Map<string, PickerProject[]>();\n PICKER_PROJECTS.forEach((project) => {\n const key = (project[field] as string) || without;\n if (!buckets.has(key)) {\n buckets.set(key, []);\n }\n buckets.get(key)?.push(project);\n });\n\n return Array.from(buckets.entries())\n .map(([name, projects]) => ({\n id: `g-${name}`,\n name,\n options: toProjectOptions(projects),\n }))\n .sort((a, b) =>\n a.name === without\n ? 1\n : b.name === without\n ? -1\n : a.name.localeCompare(b.name)\n );\n};\n\n/* ------------------------------------------------------------------ */\n/* Type + visibility option copy */\n/* ------------------------------------------------------------------ */\n\nexport const PORTFOLIO_TYPES: {\n id: PortfolioKind;\n title: string;\n description: string;\n}[] = [\n {\n id: \"custom\",\n title: \"Custom Portfolio\",\n description: \"The projects you pick by hand. Nothing joins automatically.\",\n },\n {\n id: \"client\",\n title: \"Client Portfolio\",\n description:\n \"All projects for a client company. New ones join automatically.\",\n },\n {\n id: \"leader\",\n title: \"Project Leader Portfolio\",\n description: \"All projects led by a person. New ones join automatically.\",\n },\n {\n id: \"category\",\n title: \"Category Portfolio\",\n description:\n \"All projects in a project category. New ones join automatically.\",\n },\n];\n\nexport const VISIBILITY_OPTIONS: {\n id: PortfolioVisibility;\n title: string;\n description: string;\n}[] = [\n {\n id: \"everyone\",\n title: \"Visible to Everyone\",\n description:\n \"Anyone who can use portfolios sees this one. They still only see the projects they already have access to.\",\n },\n {\n id: \"me\",\n title: \"Visible Only to Me\",\n description: \"Nobody else sees this portfolio.\",\n },\n];\n\nexport const contextFieldLabel = (type: PortfolioKind): string =>\n type === \"custom\"\n ? \"Projects\"\n : type === \"category\"\n ? \"Category\"\n : type === \"client\"\n ? \"Client\"\n : \"Project Leader\";\n\nexport const leaderShortName = (name: string): string =>\n LEADERS_LIST.find((leader) => leader.name === name)?.short ?? name;\n\n/* Default names: \"{Category} Projects\", \"{Client} Projects\", \"Lead by {N.}\". */\nexport const defaultPortfolioName = (\n type: PortfolioKind,\n context: string\n): string => {\n if (!context) return \"\";\n if (type === \"category\" || type === \"client\") return `${context} Projects`;\n if (type === \"leader\") return `Lead by ${leaderShortName(context)}`;\n return \"\";\n};\n\n/* ------------------------------------------------------------------ */\n/* Validation (shared by create step 2 and the edit dialog) */\n/* ------------------------------------------------------------------ */\n\n/** Name is required; a custom portfolio needs at least one project, a context\n portfolio needs its context chosen. Same rule for create and edit. */\nexport const isPortfolioDetailsValid = (values: PortfolioFormValues): boolean =>\n values.name.trim().length > 0 &&\n (values.type === \"custom\"\n ? values.projectIds.length > 0\n : Boolean(values.context));\n\n/* ------------------------------------------------------------------ */\n/* Pickers */\n/* ------------------------------------------------------------------ */\n\n/* Group-by control: the SortGeneralIcon button the Invite-to-Projects picker\n shows as the search bar's right-side adornment. Controls grouping, not sort. */\nconst ProjectsGroupBy = ({\n selected,\n onChange,\n}: {\n selected: GroupBy;\n onChange: (groupBy: GroupBy) => void;\n}): ReactElement => (\n <Select\n keepSameOptionsOrder\n disableSearch\n disabledInternalSort\n forceCloseMenu\n position=\"bottom-end\"\n selected={selected}\n onChange={(value) => onChange(value as GroupBy)}\n options={GROUP_BY_OPTIONS}\n target={\n <IconButton type=\"button\" variant=\"text gray\">\n <SortGeneralIcon />\n </IconButton>\n }\n />\n);\n\nconst ProjectsPicker = ({\n selected,\n onChange,\n groupBy,\n onGroupBy,\n invalid,\n}: {\n selected: string[];\n onChange: (ids: string[]) => void;\n groupBy: GroupBy;\n onGroupBy: (groupBy: GroupBy) => void;\n invalid?: boolean;\n}): ReactElement => {\n const options = useMemo(() => groupPickerProjects(groupBy), [groupBy]);\n const count = selected.length;\n const triggerText =\n count === 0\n ? \"Choose projects\"\n : count === 1\n ? \"1 project selected\"\n : `${count} projects selected`;\n return (\n <Select\n type=\"multiple\"\n options={options}\n selected={selected}\n onChange={(value) => onChange(value as string[])}\n noResultText=\"No results\"\n endAdornment={<ProjectsGroupBy selected={groupBy} onChange={onGroupBy} />}\n target={\n <SelectTrigger\n id=\"pf-projects\"\n className=\"pf-trigger\"\n invalid={invalid}\n typographyProps={{ color: count > 0 ? \"primary\" : \"quaternary\" }}\n >\n {triggerText}\n </SelectTrigger>\n }\n />\n );\n};\n\nconst ContextPicker = ({\n type,\n value,\n onChange,\n invalid,\n}: {\n type: PortfolioKind;\n value?: string;\n onChange: (value: string) => void;\n invalid?: boolean;\n}): ReactElement => {\n const options =\n type === \"category\"\n ? CATEGORIES.map((name) => ({ id: name, name }))\n : type === \"client\"\n ? CLIENTS.map((name) => ({ id: name, name }))\n : LEADERS_LIST.map((leader) => ({ id: leader.name, name: leader.name }));\n const placeholder =\n type === \"category\"\n ? \"Choose a category\"\n : type === \"client\"\n ? \"Choose a client\"\n : \"Choose a project leader\";\n return (\n <Select\n forceCloseMenu\n options={options}\n selected={value ?? \"\"}\n onChange={(next) => onChange(String(next))}\n target={\n <SelectTrigger\n id=\"pf-context\"\n className=\"pf-trigger\"\n invalid={invalid}\n typographyProps={{ color: value ? \"primary\" : \"quaternary\" }}\n >\n {value ?? placeholder}\n </SelectTrigger>\n }\n />\n );\n};\n\n/* ------------------------------------------------------------------ */\n/* The reusable form body */\n/* ------------------------------------------------------------------ */\n\nconst StyledDetailsForm = styled.div`\n display: flex;\n flex-direction: column;\n gap: 24px;\n\n .field {\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n /* DS form controls are fixed-width (Input 360px, SelectTrigger 300px); let\n them fill the dialog column instead. */\n .field .c-input-wrapper {\n width: 100%;\n }\n\n .field .pf-trigger {\n width: 100%;\n }\n`;\n\nexport interface PortfolioDetailsFieldsProps {\n values: PortfolioFormValues;\n onName: (value: string) => void;\n onContext: (value: string) => void;\n onProjects: (ids: string[]) => void;\n onGroupBy: (groupBy: GroupBy) => void;\n onVisibility: (value: PortfolioVisibility) => void;\n /* Form pattern (propagating through the app): the submit button is ALWAYS\n enabled. On submit the consumer flips showErrors; each field then outlines\n itself (aria-invalid) while it is invalid, and clears once it becomes\n valid. No field disables submit. */\n showErrors: boolean;\n}\n\n/** Name + the type's picker + visibility. No Dialog wrappers and no action\n button — the consumer (create step or edit dialog) supplies those. */\nexport const PortfolioDetailsFields = ({\n values,\n onName,\n onContext,\n onProjects,\n onGroupBy,\n onVisibility,\n showErrors,\n}: PortfolioDetailsFieldsProps): ReactElement => {\n const { type, name, context, projectIds, groupBy, visibility } = values;\n const nameInvalid = showErrors && name.trim().length === 0;\n const pickerInvalid =\n showErrors && (type === \"custom\" ? projectIds.length === 0 : !context);\n\n return (\n <StyledDetailsForm>\n <div className=\"field\">\n <Label htmlFor=\"pf-name\">Name</Label>\n <Input\n id=\"pf-name\"\n value={name}\n placeholder=\"Portfolio name\"\n invalid={nameInvalid}\n onChange={(event) => onName(event.target.value)}\n />\n </div>\n <div className=\"field\">\n <Label htmlFor={type === \"custom\" ? \"pf-projects\" : \"pf-context\"}>\n {contextFieldLabel(type)}\n </Label>\n {type === \"custom\" ? (\n <ProjectsPicker\n selected={projectIds}\n onChange={onProjects}\n groupBy={groupBy}\n onGroupBy={onGroupBy}\n invalid={pickerInvalid}\n />\n ) : (\n <ContextPicker\n type={type}\n value={context}\n onChange={onContext}\n invalid={pickerInvalid}\n />\n )}\n </div>\n <div className=\"field\">\n <RadioGroup\n label=\"Visibility\"\n variant=\"plain\"\n value={visibility}\n onChange={(value) => onVisibility(value as PortfolioVisibility)}\n options={VISIBILITY_OPTIONS.map((option) => ({\n id: option.id,\n name: option.title,\n description: option.description,\n }))}\n />\n </div>\n </StyledDetailsForm>\n );\n};\n\nPortfolioDetailsFields.displayName = \"PortfolioDetailsFields\";\n\n/* ------------------------------------------------------------------ */\n/* Edit Portfolio dialog — the create wizard's step 2, on its own */\n/* ------------------------------------------------------------------ */\n\nexport interface EditPortfolioDialogProps {\n open: boolean;\n /** The portfolio's current values; the dialog seeds itself from these on\n open, so Cancel discards edits and Save commits them. */\n initialValues: PortfolioFormValues;\n onClose: () => void;\n onSave?: (values: PortfolioFormValues) => void;\n}\n\n/*\n Same fields, same validation as create step 2. The type is fixed to the\n portfolio's kind (edit changes the details, not the kind), so there is no\n type radio here — only the name, the type's picker, and visibility.\n*/\nexport const EditPortfolioDialog = ({\n open,\n initialValues,\n onClose,\n onSave,\n}: EditPortfolioDialogProps): ReactElement => {\n const [values, setValues] = useState<PortfolioFormValues>(initialValues);\n const [showErrors, setShowErrors] = useState(false);\n\n /* Re-seed from the portfolio each time the dialog opens. */\n useEffect(() => {\n if (open) {\n setValues(initialValues);\n setShowErrors(false);\n }\n // Seed on open only — initialValues is read at that moment by design.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n const patch = (next: Partial<PortfolioFormValues>): void =>\n setValues((current) => ({ ...current, ...next }));\n\n const handleSave = (): void => {\n if (!isPortfolioDetailsValid(values)) {\n setShowErrors(true);\n return;\n }\n onSave?.(values);\n onClose();\n };\n\n return (\n <Dialog open={open} onClose={onClose} disableCloseOnEsc>\n <Dialog.Title>Edit Portfolio</Dialog.Title>\n <Dialog.ContentDivider />\n <Dialog.Content>\n <PortfolioDetailsFields\n values={values}\n onName={(name) => patch({ name })}\n onContext={(context) => patch({ context })}\n onProjects={(projectIds) => patch({ projectIds })}\n onGroupBy={(groupBy) => patch({ groupBy })}\n onVisibility={(visibility) => patch({ visibility })}\n showErrors={showErrors}\n />\n </Dialog.Content>\n <Dialog.ContentDivider />\n <Dialog.Actions>\n <Button\n variant=\"primary\"\n style={{ marginRight: \"12px\" }}\n onClick={handleSave}\n >\n Save Changes\n </Button>\n <Button variant=\"secondary\" data-action=\"cancel\" onClick={onClose}>\n Cancel\n </Button>\n </Dialog.Actions>\n </Dialog>\n );\n};\n\nEditPortfolioDialog.displayName = \"EditPortfolioDialog\";\n"],"mappings":"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","ignoreList":[]}
package/dist/index.js CHANGED
@@ -26196,16 +26196,52 @@
26196
26196
  var StyledMedia = styled__default["default"].div.withConfig({
26197
26197
  displayName: "Styles__StyledMedia",
26198
26198
  componentId: "sc-zjz7mh-0"
26199
- })(["display:flex;flex-direction:column;gap:", ";width:100%;.c-media-frame{", "}.c-media-frame img{display:block;width:100%;height:auto;}"], SPACE.sm, function (_ref) {
26199
+ })(["display:flex;flex-direction:column;gap:", ";width:100%;.c-media-frame{width:fit-content;max-width:100%;margin-inline:auto;", "}.c-media-frame img{display:block;height:auto;", "}"], SPACE.sm, function (_ref) {
26200
26200
  var $bordered = _ref.$bordered;
26201
26201
  return $bordered && styled.css(["overflow:hidden;border:1px solid var(--border-primary);border-radius:", ";"], "0.5rem");
26202
+ }, function (_ref2) {
26203
+ var $sized = _ref2.$sized;
26204
+ return $sized ? styled.css(["max-width:100%;"]) : styled.css(["width:100%;"]);
26202
26205
  });
26203
26206
  StyledMedia.displayName = "StyledMedia";
26204
26207
 
26205
- var _excluded$q = ["src", "alt", "variant", "caption"];
26208
+ var _excluded$q = ["src", "alt", "variant", "caption", "width", "height", "density"];
26209
+ /** A tall image (height greater than width) is capped at this display height. */
26210
+ var MEDIA_PORTRAIT_MAX_HEIGHT = 680;
26211
+
26212
+ /**
26213
+ * The box the `<img>` is laid out in, in CSS pixels. A portrait image taller
26214
+ * than the cap is scaled down to the cap, keeping its aspect ratio. Resolving
26215
+ * the cap here — rather than with `width: auto; max-height` in CSS — keeps the
26216
+ * size independent of the file's natural pixel size, so a 2x capture without a
26217
+ * `density` (and therefore no `srcset` descriptor) never renders upscaled.
26218
+ */
26219
+ var displaySize = function displaySize(width, height) {
26220
+ if (width == null || height == null) {
26221
+ return undefined;
26222
+ }
26223
+ if (height > width && height > MEDIA_PORTRAIT_MAX_HEIGHT) {
26224
+ return {
26225
+ width: Math.round(width * MEDIA_PORTRAIT_MAX_HEIGHT / height),
26226
+ height: MEDIA_PORTRAIT_MAX_HEIGHT
26227
+ };
26228
+ }
26229
+ return {
26230
+ width,
26231
+ height
26232
+ };
26233
+ };
26234
+
26206
26235
  /**
26207
26236
  * An image block: a screenshot renders framed (border, no shadow), a flat
26208
26237
  * illustration renders without a frame. The caption sits below the frame.
26238
+ *
26239
+ * `width`/`height` are the image's real display size in CSS pixels, measured
26240
+ * at compile time. When present, the image renders at that size — centered,
26241
+ * capped at the column width, never upscaled — and the `<img>` reserves the
26242
+ * space so the layout does not jump as it loads. A tall image (height greater
26243
+ * than width) is capped by height instead. When absent (e.g. a remote source
26244
+ * the build could not measure), the image falls back to the column-width cap.
26209
26245
  */
26210
26246
  var Media = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
26211
26247
  var src = _ref.src,
@@ -26213,15 +26249,23 @@
26213
26249
  _ref$variant = _ref.variant,
26214
26250
  variant = _ref$variant === void 0 ? "illustration" : _ref$variant,
26215
26251
  caption = _ref.caption,
26252
+ width = _ref.width,
26253
+ height = _ref.height,
26254
+ density = _ref.density,
26216
26255
  rest = _objectWithoutProperties(_ref, _excluded$q);
26256
+ var size = displaySize(width, height);
26217
26257
  return /*#__PURE__*/React__default["default"].createElement(StyledMedia, _extends({
26218
26258
  ref: ref,
26219
- $bordered: variant === "screenshot"
26259
+ $bordered: variant === "screenshot",
26260
+ $sized: size !== undefined
26220
26261
  }, rest), /*#__PURE__*/React__default["default"].createElement("div", {
26221
26262
  className: "c-media-frame"
26222
26263
  }, /*#__PURE__*/React__default["default"].createElement("img", {
26223
26264
  src: src,
26224
- alt: alt !== null && alt !== void 0 ? alt : ""
26265
+ alt: alt !== null && alt !== void 0 ? alt : "",
26266
+ width: size === null || size === void 0 ? void 0 : size.width,
26267
+ height: size === null || size === void 0 ? void 0 : size.height,
26268
+ srcSet: density ? "".concat(src, " ").concat(density, "x") : undefined
26225
26269
  })), caption ? /*#__PURE__*/React__default["default"].createElement(Caption1, {
26226
26270
  color: "secondary"
26227
26271
  }, caption) : null);
@@ -26413,7 +26457,10 @@
26413
26457
  src = _ref1.src,
26414
26458
  alt = _ref1.alt,
26415
26459
  variant = _ref1.variant,
26416
- caption = _ref1.caption;
26460
+ caption = _ref1.caption,
26461
+ width = _ref1.width,
26462
+ height = _ref1.height,
26463
+ density = _ref1.density;
26417
26464
 
26418
26465
  // Video (and future) variants carry service semantics, so their renderer
26419
26466
  // is application-catalog territory — an injected `media` override. The
@@ -26427,7 +26474,10 @@
26427
26474
  src: src,
26428
26475
  alt: alt,
26429
26476
  variant: variant,
26430
- caption: caption
26477
+ caption: caption,
26478
+ width: width,
26479
+ height: height,
26480
+ density: density
26431
26481
  });
26432
26482
  },
26433
26483
  "titled-text": function titledText(_ref10) {
@@ -31013,6 +31063,7 @@
31013
31063
  exports.ListSeparator = ListSeparator;
31014
31064
  exports.LockIcon = LockIcon$1;
31015
31065
  exports.LockSmallIcon = LockSmallIcon$1;
31066
+ exports.MEDIA_PORTRAIT_MAX_HEIGHT = MEDIA_PORTRAIT_MAX_HEIGHT;
31016
31067
  exports.MarkerIcon = MarkerIcon$1;
31017
31068
  exports.MeasuredPane = MeasuredPane;
31018
31069
  exports.Media = Media;