bsmnt 0.12.0 → 0.13.1
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/application/add-integration/index.d.ts.map +1 -1
- package/dist/application/add-integration/index.js +23 -0
- package/dist/application/add-integration/index.js.map +1 -1
- package/dist/domain/consent.d.ts +17 -0
- package/dist/domain/consent.d.ts.map +1 -0
- package/dist/domain/consent.js +13 -0
- package/dist/domain/consent.js.map +1 -0
- package/dist/domain/integration.d.ts +19 -2
- package/dist/domain/integration.d.ts.map +1 -1
- package/dist/domain/integration.js +10 -1
- package/dist/domain/integration.js.map +1 -1
- package/dist/domain/jobs.d.ts +17 -0
- package/dist/domain/jobs.d.ts.map +1 -0
- package/dist/domain/jobs.js +13 -0
- package/dist/domain/jobs.js.map +1 -0
- package/dist/domain/skills.d.ts +23 -2
- package/dist/domain/skills.d.ts.map +1 -1
- package/dist/domain/skills.js +23 -2
- package/dist/domain/skills.js.map +1 -1
- package/dist/domain/templates.d.ts +7 -1
- package/dist/domain/templates.d.ts.map +1 -1
- package/dist/domain/templates.js +2 -0
- package/dist/domain/templates.js.map +1 -1
- package/dist/index.js +34 -9
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/create/setup-agent.d.ts.map +1 -1
- package/dist/infrastructure/create/setup-agent.js +11 -4
- package/dist/infrastructure/create/setup-agent.js.map +1 -1
- package/dist/infrastructure/integrations/inject-integration.d.ts.map +1 -1
- package/dist/infrastructure/integrations/inject-integration.js +36 -2
- package/dist/infrastructure/integrations/inject-integration.js.map +1 -1
- package/dist/modules/features/consent/ketch/config.d.ts +18 -0
- package/dist/modules/features/consent/ketch/config.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/config.js +24 -0
- package/dist/modules/features/consent/ketch/config.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/biome.d.ts +16 -0
- package/dist/modules/features/consent/ketch/mergers/biome.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/biome.js +31 -0
- package/dist/modules/features/consent/ketch/mergers/biome.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/check-integration.d.ts +13 -0
- package/dist/modules/features/consent/ketch/mergers/check-integration.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/check-integration.js +64 -0
- package/dist/modules/features/consent/ketch/mergers/check-integration.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/env-example.d.ts +12 -0
- package/dist/modules/features/consent/ketch/mergers/env-example.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/env-example.js +28 -0
- package/dist/modules/features/consent/ketch/mergers/env-example.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/footer.d.ts +17 -0
- package/dist/modules/features/consent/ketch/mergers/footer.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/footer.js +40 -0
- package/dist/modules/features/consent/ketch/mergers/footer.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/knip.d.ts +18 -0
- package/dist/modules/features/consent/ketch/mergers/knip.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/knip.js +37 -0
- package/dist/modules/features/consent/ketch/mergers/knip.js.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/layout.d.ts +25 -0
- package/dist/modules/features/consent/ketch/mergers/layout.d.ts.map +1 -0
- package/dist/modules/features/consent/ketch/mergers/layout.js +55 -0
- package/dist/modules/features/consent/ketch/mergers/layout.js.map +1 -0
- package/dist/modules/features/jobs/ashby/config.d.ts +19 -0
- package/dist/modules/features/jobs/ashby/config.d.ts.map +1 -0
- package/dist/modules/features/jobs/ashby/config.js +29 -0
- package/dist/modules/features/jobs/ashby/config.js.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/check-integration.d.ts +14 -0
- package/dist/modules/features/jobs/ashby/mergers/check-integration.d.ts.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/check-integration.js +78 -0
- package/dist/modules/features/jobs/ashby/mergers/check-integration.js.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/env-example.d.ts +12 -0
- package/dist/modules/features/jobs/ashby/mergers/env-example.d.ts.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/env-example.js +27 -0
- package/dist/modules/features/jobs/ashby/mergers/env-example.js.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/knip.d.ts +18 -0
- package/dist/modules/features/jobs/ashby/mergers/knip.d.ts.map +1 -0
- package/dist/modules/features/jobs/ashby/mergers/knip.js +41 -0
- package/dist/modules/features/jobs/ashby/mergers/knip.js.map +1 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +12 -0
- package/dist/paths.js.map +1 -1
- package/package.json +3 -1
- package/src/agent-skills/ashby-pagebuilder-block/SKILL.md +277 -0
- package/src/agent-skills/hubspot-pagebuilder-block/SKILL.md +58 -25
- package/src/agent-skills/ketch-consent-check/SKILL.md +197 -0
- package/src/agent-skills/ketch-consent-setup/SKILL.md +326 -0
- package/src/agent-skills/ketch-consent-setup/references/ui-customization.md +329 -0
- package/src/agent-skills/page-builder-block/SKILL.md +150 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/anchor-id-input.tsx +17 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/presentation-input.tsx +146 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/components/spacing-steps-input.tsx +84 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/fetchers/layout.ts +6 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/icons.ts +8 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/page-builder-config.ts +1 -1
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/presentation.ts +47 -15
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/queries.ts +12 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +5 -5
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/description.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/gated-content.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/hero.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/reusable/rich-text-block.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/index.ts +8 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/layout/spacing-settings.ts +120 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/anchor.ts +75 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/block.ts +46 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/presentation.ts +44 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/schemas/shared/spacing.ts +164 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/singletons.ts +7 -0
- package/src/modules/features/cms/sanity-pagebuilder/files/lib/integrations/sanity/structure.ts +4 -4
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/anchor-id-input.tsx +17 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/presentation-input.tsx +146 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/components/spacing-steps-input.tsx +84 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/fetchers/layout.ts +4 -2
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/icons.ts +8 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/page-builder-config.ts +1 -1
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/presentation.ts +47 -15
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/queries.ts +12 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/blog-content.ts +5 -5
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/description.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/gated-content.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/hero.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/reusable/rich-text-block.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/components/singleton/content-collection.ts +3 -3
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/index.ts +8 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/layout/spacing-settings.ts +120 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/anchor.ts +75 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/block.ts +46 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/presentation.ts +44 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/schemas/shared/spacing.ts +164 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/singletons.ts +7 -0
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/structure.ts +4 -4
- package/src/modules/features/cms/sanity-pagebuilder-cache/files/lib/integrations/sanity/tags.ts +2 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/check-integration.ts +25 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/README.md +70 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/categories.ts +20 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/consent-store.ts +107 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/env.ts +20 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/ketch-experience.css +136 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/preferences-button.tsx +51 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/script.tsx +8 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/types.ts +15 -0
- package/src/modules/features/consent/ketch/files/lib/integrations/ketch/use-consent.ts +26 -0
- package/src/modules/features/jobs/ashby/files/_sanity-adapter/job-board-block.ts +53 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/README.md +134 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/env.ts +3 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/index.ts +40 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/normalize.ts +124 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/ashby/types.ts +20 -0
- package/src/modules/features/jobs/ashby/files/lib/integrations/check-integration.ts +25 -0
- package/src/templates/next-default/lib/utils/README.md +1 -0
- package/src/templates/next-default/lib/utils/image-sizes.ts +64 -25
- package/src/templates/next-experiments/lib/utils/README.md +1 -0
- package/src/templates/next-experiments/lib/utils/image-sizes.ts +64 -25
- package/src/templates/next-pagebuilder/AGENTS.md +129 -0
- package/src/templates/next-pagebuilder/CLAUDE.md +3 -0
- package/src/templates/next-pagebuilder/README.md +70 -0
- package/src/templates/next-pagebuilder/app/(content)/layout.tsx +2 -0
- package/src/templates/next-pagebuilder/components/layout/spacing-scale/index.tsx +18 -0
- package/src/templates/next-pagebuilder/components/page-builder/components/article-content/index.tsx +1 -1
- package/src/templates/next-pagebuilder/components/page-builder/components/content-collection/index.tsx +2 -2
- package/src/templates/next-pagebuilder/components/page-builder/components/description.tsx +3 -7
- package/src/templates/next-pagebuilder/components/page-builder/components/gated-content/index.tsx +2 -2
- package/src/templates/next-pagebuilder/components/page-builder/components/hero.tsx +3 -7
- package/src/templates/next-pagebuilder/components/page-builder/components/rich-text-block.tsx +3 -5
- package/src/templates/next-pagebuilder/components/page-builder/registry.tsx +70 -0
- package/src/templates/next-pagebuilder/components/page-builder/renderer.tsx +33 -49
- package/src/templates/next-pagebuilder/components/page-builder/section.tsx +35 -0
- package/src/templates/next-pagebuilder/components/page-document/index.tsx +2 -2
- package/src/templates/next-pagebuilder/lib/integrations/sanity/sanity.types.ts +92 -4
- package/src/templates/next-pagebuilder/lib/utils/image-sizes.ts +64 -25
- package/src/templates/next-pagebuilder-cache/AGENTS.md +136 -0
- package/src/templates/next-pagebuilder-cache/CLAUDE.md +3 -0
- package/src/templates/next-pagebuilder-cache/README.md +75 -0
- package/src/templates/next-pagebuilder-cache/app/(content)/layout.tsx +2 -0
- package/src/templates/next-pagebuilder-cache/components/layout/spacing-scale/index.tsx +46 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/article-content/index.tsx +1 -1
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/content-collection/index.tsx +2 -2
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/description.tsx +3 -7
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/gated-content/index.tsx +2 -2
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/hero.tsx +3 -7
- package/src/templates/next-pagebuilder-cache/components/page-builder/components/rich-text-block.tsx +3 -5
- package/src/templates/next-pagebuilder-cache/components/page-builder/registry.tsx +70 -0
- package/src/templates/next-pagebuilder-cache/components/page-builder/renderer.tsx +33 -49
- package/src/templates/next-pagebuilder-cache/components/page-builder/section.tsx +35 -0
- package/src/templates/next-pagebuilder-cache/components/page-document/index.tsx +2 -2
- package/src/templates/next-pagebuilder-cache/lib/integrations/sanity/sanity.types.ts +92 -4
- package/src/templates/next-pagebuilder-cache/lib/utils/image-sizes.ts +64 -25
- package/src/templates/next-webgl/lib/utils/README.md +1 -0
- package/src/templates/next-webgl/lib/utils/image-sizes.ts +64 -25
|
@@ -15,40 +15,55 @@ export type ByBreakpoint<
|
|
|
15
15
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
16
16
|
> = { base: T } & Partial<Record<Extract<keyof B, string>, T>>
|
|
17
17
|
|
|
18
|
+
export type ImageSizesOptions<
|
|
19
|
+
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
20
|
+
> = { breakpoints?: B }
|
|
21
|
+
|
|
22
|
+
export type GridImageSizesOptions<
|
|
23
|
+
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
24
|
+
> = ImageSizesOptions<B> & {
|
|
25
|
+
/** The grid container's `max-width` in px, past which columns stop growing. */
|
|
26
|
+
maxWidth?: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type Condition<T> = { min: number; value: T }
|
|
30
|
+
|
|
18
31
|
function columnWidth(columns: number): string {
|
|
19
32
|
return `${Math.round(100 / columns)}vw`
|
|
20
33
|
}
|
|
21
34
|
|
|
35
|
+
function toConditions<T>(
|
|
36
|
+
overrides: Readonly<Record<string, T | undefined>>,
|
|
37
|
+
scale: BreakpointMap
|
|
38
|
+
): Condition<T>[] {
|
|
39
|
+
return Object.entries(overrides).flatMap(([name, value]) => {
|
|
40
|
+
const min = scale[name]
|
|
41
|
+
return value !== undefined && min !== undefined ? [{ min, value }] : []
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
22
45
|
/**
|
|
23
46
|
* Widest first, since `sizes` takes the first matching condition and the last
|
|
24
47
|
* entry must be bare. `min-width` matches the Tailwind variant's boundary; a
|
|
25
48
|
* `max-width: <next> - 1` one would leave a fractional-pixel gap.
|
|
26
49
|
*/
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
overrides: Readonly<Record<string, string | undefined>>,
|
|
30
|
-
scale: BreakpointMap
|
|
31
|
-
): string {
|
|
32
|
-
const conditions: string[] = []
|
|
33
|
-
|
|
34
|
-
for (const [name, min] of Object.entries(scale).sort(
|
|
35
|
-
([, a], [, b]) => b - a
|
|
36
|
-
)) {
|
|
37
|
-
const value = overrides[name]
|
|
38
|
-
if (value !== undefined) {
|
|
39
|
-
conditions.push(`(min-width: ${min}px) ${value}`)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
50
|
+
function joinSizes(base: string, conditions: Condition<string>[]): string {
|
|
51
|
+
const sorted = [...conditions].sort((a, b) => b.min - a.min)
|
|
42
52
|
|
|
43
|
-
return [
|
|
53
|
+
return [
|
|
54
|
+
...sorted.map(({ min, value }) => `(min-width: ${min}px) ${value}`),
|
|
55
|
+
base,
|
|
56
|
+
].join(", ")
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
/** Builds `sizes` from the CSS length the image renders at per breakpoint. */
|
|
47
60
|
export function buildImageSizes<
|
|
48
61
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
49
|
-
>(widths: ByBreakpoint<string, B>,
|
|
62
|
+
>(widths: ByBreakpoint<string, B>, options: ImageSizesOptions<B> = {}): string {
|
|
50
63
|
const { base, ...overrides } = widths
|
|
51
|
-
|
|
64
|
+
const scale = options.breakpoints ?? BASEMENT_BREAKPOINTS
|
|
65
|
+
|
|
66
|
+
return joinSizes(base, toConditions<string>(overrides, scale))
|
|
52
67
|
}
|
|
53
68
|
|
|
54
69
|
/**
|
|
@@ -58,15 +73,39 @@ export function buildImageSizes<
|
|
|
58
73
|
*/
|
|
59
74
|
export function buildGridImageSizes<
|
|
60
75
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
61
|
-
>(
|
|
76
|
+
>(
|
|
77
|
+
columns: ByBreakpoint<number, B>,
|
|
78
|
+
options: GridImageSizesOptions<B> = {}
|
|
79
|
+
): string {
|
|
80
|
+
const { maxWidth, breakpoints } = options
|
|
62
81
|
const { base, ...overrides } = columns
|
|
63
|
-
const
|
|
82
|
+
const steps = toConditions<number>(
|
|
83
|
+
overrides,
|
|
84
|
+
breakpoints ?? BASEMENT_BREAKPOINTS
|
|
85
|
+
)
|
|
86
|
+
const cap =
|
|
87
|
+
maxWidth !== undefined && Number.isFinite(maxWidth) && maxWidth > 0
|
|
88
|
+
? maxWidth
|
|
89
|
+
: undefined
|
|
90
|
+
|
|
91
|
+
// The cap rarely lands on a breakpoint, so it needs its own condition.
|
|
92
|
+
if (cap !== undefined && !steps.some(({ min }) => min === cap)) {
|
|
93
|
+
const below = steps
|
|
94
|
+
.filter(({ min }) => min < cap)
|
|
95
|
+
.sort((a, b) => a.min - b.min)
|
|
96
|
+
.at(-1)
|
|
64
97
|
|
|
65
|
-
|
|
66
|
-
if (count !== undefined) {
|
|
67
|
-
widths[name] = columnWidth(count)
|
|
68
|
-
}
|
|
98
|
+
steps.push({ min: cap, value: below?.value ?? base })
|
|
69
99
|
}
|
|
70
100
|
|
|
71
|
-
return
|
|
101
|
+
return joinSizes(
|
|
102
|
+
columnWidth(base),
|
|
103
|
+
steps.map(({ min, value }) => ({
|
|
104
|
+
min,
|
|
105
|
+
value:
|
|
106
|
+
cap !== undefined && min >= cap
|
|
107
|
+
? `${Math.round(cap / value)}px`
|
|
108
|
+
: columnWidth(value),
|
|
109
|
+
}))
|
|
110
|
+
)
|
|
72
111
|
}
|
|
@@ -45,6 +45,7 @@ export const metadata = generatePageMetadata({ title: 'About' })
|
|
|
45
45
|
// next/image sizes — keys mirror the element's Tailwind variants
|
|
46
46
|
buildImageSizes({ base: '100vw', desktop: '796px' })
|
|
47
47
|
buildGridImageSizes({ base: 1, tablet: 2, desktop: 3 })
|
|
48
|
+
buildGridImageSizes({ base: 1, tablet: 2, desktop: 3 }, { maxWidth: 1440 })
|
|
48
49
|
|
|
49
50
|
// Refs — in a component, use the hook: an inline mergeRefs([...]) is a new
|
|
50
51
|
// callback each render, so React detaches and reattaches every ref.
|
|
@@ -15,40 +15,55 @@ export type ByBreakpoint<
|
|
|
15
15
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
16
16
|
> = { base: T } & Partial<Record<Extract<keyof B, string>, T>>
|
|
17
17
|
|
|
18
|
+
export type ImageSizesOptions<
|
|
19
|
+
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
20
|
+
> = { breakpoints?: B }
|
|
21
|
+
|
|
22
|
+
export type GridImageSizesOptions<
|
|
23
|
+
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
24
|
+
> = ImageSizesOptions<B> & {
|
|
25
|
+
/** The grid container's `max-width` in px, past which columns stop growing. */
|
|
26
|
+
maxWidth?: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type Condition<T> = { min: number; value: T }
|
|
30
|
+
|
|
18
31
|
function columnWidth(columns: number): string {
|
|
19
32
|
return `${Math.round(100 / columns)}vw`
|
|
20
33
|
}
|
|
21
34
|
|
|
35
|
+
function toConditions<T>(
|
|
36
|
+
overrides: Readonly<Record<string, T | undefined>>,
|
|
37
|
+
scale: BreakpointMap
|
|
38
|
+
): Condition<T>[] {
|
|
39
|
+
return Object.entries(overrides).flatMap(([name, value]) => {
|
|
40
|
+
const min = scale[name]
|
|
41
|
+
return value !== undefined && min !== undefined ? [{ min, value }] : []
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
22
45
|
/**
|
|
23
46
|
* Widest first, since `sizes` takes the first matching condition and the last
|
|
24
47
|
* entry must be bare. `min-width` matches the Tailwind variant's boundary; a
|
|
25
48
|
* `max-width: <next> - 1` one would leave a fractional-pixel gap.
|
|
26
49
|
*/
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
overrides: Readonly<Record<string, string | undefined>>,
|
|
30
|
-
scale: BreakpointMap
|
|
31
|
-
): string {
|
|
32
|
-
const conditions: string[] = []
|
|
33
|
-
|
|
34
|
-
for (const [name, min] of Object.entries(scale).sort(
|
|
35
|
-
([, a], [, b]) => b - a
|
|
36
|
-
)) {
|
|
37
|
-
const value = overrides[name]
|
|
38
|
-
if (value !== undefined) {
|
|
39
|
-
conditions.push(`(min-width: ${min}px) ${value}`)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
50
|
+
function joinSizes(base: string, conditions: Condition<string>[]): string {
|
|
51
|
+
const sorted = [...conditions].sort((a, b) => b.min - a.min)
|
|
42
52
|
|
|
43
|
-
return [
|
|
53
|
+
return [
|
|
54
|
+
...sorted.map(({ min, value }) => `(min-width: ${min}px) ${value}`),
|
|
55
|
+
base,
|
|
56
|
+
].join(", ")
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
/** Builds `sizes` from the CSS length the image renders at per breakpoint. */
|
|
47
60
|
export function buildImageSizes<
|
|
48
61
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
49
|
-
>(widths: ByBreakpoint<string, B>,
|
|
62
|
+
>(widths: ByBreakpoint<string, B>, options: ImageSizesOptions<B> = {}): string {
|
|
50
63
|
const { base, ...overrides } = widths
|
|
51
|
-
|
|
64
|
+
const scale = options.breakpoints ?? BASEMENT_BREAKPOINTS
|
|
65
|
+
|
|
66
|
+
return joinSizes(base, toConditions<string>(overrides, scale))
|
|
52
67
|
}
|
|
53
68
|
|
|
54
69
|
/**
|
|
@@ -58,15 +73,39 @@ export function buildImageSizes<
|
|
|
58
73
|
*/
|
|
59
74
|
export function buildGridImageSizes<
|
|
60
75
|
B extends BreakpointMap = typeof BASEMENT_BREAKPOINTS,
|
|
61
|
-
>(
|
|
76
|
+
>(
|
|
77
|
+
columns: ByBreakpoint<number, B>,
|
|
78
|
+
options: GridImageSizesOptions<B> = {}
|
|
79
|
+
): string {
|
|
80
|
+
const { maxWidth, breakpoints } = options
|
|
62
81
|
const { base, ...overrides } = columns
|
|
63
|
-
const
|
|
82
|
+
const steps = toConditions<number>(
|
|
83
|
+
overrides,
|
|
84
|
+
breakpoints ?? BASEMENT_BREAKPOINTS
|
|
85
|
+
)
|
|
86
|
+
const cap =
|
|
87
|
+
maxWidth !== undefined && Number.isFinite(maxWidth) && maxWidth > 0
|
|
88
|
+
? maxWidth
|
|
89
|
+
: undefined
|
|
90
|
+
|
|
91
|
+
// The cap rarely lands on a breakpoint, so it needs its own condition.
|
|
92
|
+
if (cap !== undefined && !steps.some(({ min }) => min === cap)) {
|
|
93
|
+
const below = steps
|
|
94
|
+
.filter(({ min }) => min < cap)
|
|
95
|
+
.sort((a, b) => a.min - b.min)
|
|
96
|
+
.at(-1)
|
|
64
97
|
|
|
65
|
-
|
|
66
|
-
if (count !== undefined) {
|
|
67
|
-
widths[name] = columnWidth(count)
|
|
68
|
-
}
|
|
98
|
+
steps.push({ min: cap, value: below?.value ?? base })
|
|
69
99
|
}
|
|
70
100
|
|
|
71
|
-
return
|
|
101
|
+
return joinSizes(
|
|
102
|
+
columnWidth(base),
|
|
103
|
+
steps.map(({ min, value }) => ({
|
|
104
|
+
min,
|
|
105
|
+
value:
|
|
106
|
+
cap !== undefined && min >= cap
|
|
107
|
+
? `${Math.round(cap / value)}px`
|
|
108
|
+
: columnWidth(value),
|
|
109
|
+
}))
|
|
110
|
+
)
|
|
72
111
|
}
|