@jfdevelops/react-layout 0.8.1 → 0.8.2
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/create-config/create-resource-links.cjs +15 -10
- package/dist/create-config/create-resource-links.cjs.map +1 -1
- package/dist/create-config/create-resource-links.d.cts +7 -5
- package/dist/create-config/create-resource-links.d.cts.map +1 -1
- package/dist/create-config/create-resource-links.d.mts +7 -5
- package/dist/create-config/create-resource-links.d.mts.map +1 -1
- package/dist/create-config/create-resource-links.mjs +15 -10
- package/dist/create-config/create-resource-links.mjs.map +1 -1
- package/dist/create-config/index.d.cts +1 -1
- package/dist/create-config/index.d.mts +1 -1
- package/package.json +1 -1
|
@@ -35,15 +35,20 @@ function createResourceLinksFromConfig(isValidResource, config) {
|
|
|
35
35
|
};
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
-
function
|
|
39
|
-
if (
|
|
38
|
+
function createResourceLinkGroupId() {
|
|
39
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
40
|
+
return `group-${Math.random().toString(36).slice(2, 11)}`;
|
|
41
|
+
}
|
|
42
|
+
function createResourceLinksWithGroups(isValidResource, groups) {
|
|
43
|
+
if (!Array.isArray(groups)) throw new Error("[createResourceLinks.withGroups]: \"groups\" must be an array.");
|
|
40
44
|
return groups.map((group, index) => {
|
|
41
|
-
if (!group) throw new Error(`[createResourceLinks.
|
|
42
|
-
if (typeof group !== "object") throw new Error(`[createResourceLinks.
|
|
43
|
-
if ("label" in group && group.label !== void 0 && typeof group.label !== "string") throw new Error(`[createResourceLinks.
|
|
44
|
-
if (!("links" in group)) throw new Error(`[createResourceLinks.
|
|
45
|
-
if (typeof group.links !== "object" || group.links === null || Array.isArray(group.links)) throw new Error(`[createResourceLinks.
|
|
45
|
+
if (!group) throw new Error(`[createResourceLinks.withGroups]: group at index ${index} is required.`);
|
|
46
|
+
if (typeof group !== "object") throw new Error(`[createResourceLinks.withGroups]: group at index ${index} must be an object. Received ${typeof group}`);
|
|
47
|
+
if ("label" in group && group.label !== void 0 && typeof group.label !== "string") throw new Error(`[createResourceLinks.withGroups]: "label" must be a string for group at index ${index}. Received ${typeof group.label}`);
|
|
48
|
+
if (!("links" in group)) throw new Error(`[createResourceLinks.withGroups]: "links" is required for group at index ${index}.`);
|
|
49
|
+
if (typeof group.links !== "object" || group.links === null || Array.isArray(group.links)) throw new Error(`[createResourceLinks.withGroups]: "links" must be an object for group at index ${index}. Received ${Array.isArray(group.links) ? "array" : typeof group.links}`);
|
|
46
50
|
return {
|
|
51
|
+
id: createResourceLinkGroupId(),
|
|
47
52
|
label: "label" in group ? group.label ?? null : null,
|
|
48
53
|
icon: "icon" in group ? group.icon : null,
|
|
49
54
|
links: createResourceLinksFromConfig(isValidResource, group.links)
|
|
@@ -55,10 +60,10 @@ function createResourceLinksFn(resources) {
|
|
|
55
60
|
function createResourceLinks(config) {
|
|
56
61
|
return createResourceLinksFromConfig(isValidResource, config);
|
|
57
62
|
}
|
|
58
|
-
function
|
|
59
|
-
return
|
|
63
|
+
function withGroups(groups) {
|
|
64
|
+
return createResourceLinksWithGroups(isValidResource, groups);
|
|
60
65
|
}
|
|
61
|
-
return Object.assign(createResourceLinks, {
|
|
66
|
+
return Object.assign(createResourceLinks, { withGroups });
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-resource-links.cjs","names":["createIsValidResourceFn"],"sources":["../../src/create-config/create-resource-links.ts"],"sourcesContent":["import { ReactNode } from 'react';\nimport {\n createIsValidResourceFn,\n type LayoutResourceKey,\n type ResourceDefinition,\n} from '../resource';\n\nexport type ResourceAnchorLinkFn<Resource extends string> = (\n resource: Resource,\n) => string;\n\nexport type ResourceLinkHref<Resource extends string> =\n | string\n | ResourceAnchorLinkFn<Resource>;\n\nexport interface CreateResourceLinkOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Resource extends LayoutResourceKey<Resources>,\n> {\n /**\n * The label of the link. This is the text that will be displayed in the link.\n */\n label: string;\n /**\n * An optional icon to register with the link. This is a headless approach, meaning you have full control\n * over the icon's rendering.\n */\n icon?: ReactNode;\n /**\n * The href of the link. By default, the href will be `\"/\"`. While you **don't** need to include a hash,\n * if you do, it will override the `hash` property (if provided).\n */\n href?: ResourceLinkHref<Resource>;\n /**\n * The hash of the link. By default, the hash will be the resource name. If you need to customize it, you can provide\n * a string or a function that returns a string.\n *\n * @remarks A `\"#\"` is not required. The generated href will include it automatically.\n */\n hash?: ResourceLinkHref<Resource>;\n}\n\nexport type CreateResourceLinkConfig<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = {\n [resource in LayoutResourceKey<Resources>]?: CreateResourceLinkOptions<\n Resources,\n resource\n >;\n};\n\nexport type InferHashFromResourceLinkHref<\n Resource extends string,\n Hash extends ResourceLinkHref<Resource>,\n> = Hash extends string\n ? Hash\n : Hash extends ResourceAnchorLinkFn<Resource>\n ? ReturnType<Hash>\n : never;\n\nexport type CreatedResourceHref = {\n /**\n * The full generated href with the `hash` if provided.\n */\n full: string;\n /**\n * The given href. This is the same value as the `href` property of the config.\n */\n given: string;\n};\n\nexport type CreatedResourceLinkBase<Resource extends string> = {\n href: CreatedResourceHref;\n label: string;\n resource: Resource;\n icon: ReactNode;\n};\nexport type CreateResourceLinkWithHash<\n Resource extends string,\n Hash extends ResourceLinkHref<Resource>,\n> = Omit<CreatedResourceLinkBase<Resource>, 'href'> & {\n href: CreatedResourceHref & {\n hash: InferHashFromResourceLinkHref<Resource, Hash>;\n };\n};\n\nexport type CreatedResourceLink<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Config extends CreateResourceLinkConfig<Resources>,\n> = {\n [Resource in keyof Config]: Resource extends LayoutResourceKey<Resources>\n ? Config[Resource] extends {\n hash: infer hash extends ResourceLinkHref<Resource>;\n }\n ? CreateResourceLinkWithHash<Resource, hash>\n : CreatedResourceLinkBase<Resource>\n : never;\n}[keyof Config];\n\nexport interface CreateResourceLinksFn<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> {\n <const Config extends CreateResourceLinkConfig<Resources>>(\n config: Config,\n ): Array<CreatedResourceLink<Resources, Config>>;\n withGroup: CreateResourceLinksWithGroupFn<Resources>;\n}\n\nexport interface CreateResourceLinkGroupOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Links extends CreateResourceLinkConfig<Resources> =\n CreateResourceLinkConfig<Resources>,\n> {\n /**\n * The label of the group. This is the text that will be displayed for the group.\n */\n label?: string;\n /**\n * An optional icon to register with the group. This is a headless approach, meaning you have full control\n * over the icon's rendering.\n */\n icon?: ReactNode;\n /**\n * The resource links in this group.\n */\n links: Links;\n}\n\nexport type CreateResourceLinkGroupInput<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = CreateResourceLinkGroupOptions<\n Resources,\n CreateResourceLinkConfig<Resources>\n>;\n\nexport type CreateResourceLinksWithGroups<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Links extends CreateResourceLinkConfig<Resources>,\n> = {\n label: string | null;\n icon: ReactNode;\n links: Array<CreatedResourceLink<Resources, Links>>;\n};\n\nexport type CreateResourceLinksWithGroupFn<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = <Groups extends ReadonlyArray<CreateResourceLinkGroupInput<Resources>>>(\n groups: Groups,\n) => Array<\n Groups[number] extends CreateResourceLinkGroupOptions<Resources, infer Links>\n ? CreateResourceLinksWithGroups<Resources, Links>\n : CreateResourceLinksWithGroups<\n Resources,\n CreateResourceLinkConfig<Resources>\n >\n>;\n\nfunction resolveResourceLinkHref<Resource extends string>(\n value: ResourceLinkHref<Resource> | undefined,\n resource: Resource,\n fallback: string,\n) {\n return typeof value === 'function' ? value(resource) : (value ?? fallback);\n}\n\nfunction normalizeResourceLinkHash(hash: string) {\n return hash.replace(/^#+/, '');\n}\n\nfunction createFullResourceLinkHref(href: string, hash: string) {\n if (href.includes('#')) {\n return href;\n }\n\n return `${href}#${normalizeResourceLinkHash(hash)}`;\n}\n\nfunction createResourceLinksFromConfig<\n Resources extends ReadonlyArray<ResourceDefinition>,\n>(\n isValidResource: ReturnType<typeof createIsValidResourceFn<Resources>>,\n config: CreateResourceLinkConfig<Resources>,\n) {\n return Object.entries(config).map(([resource, config]) => {\n if (!isValidResource(resource)) {\n throw new Error(`[createResourceLinks]: Invalid resource: ${resource}`);\n }\n\n if (!config) {\n throw new Error(\n `[createResourceLinks]: \"config\" is required for the ${resource} resource.`,\n );\n }\n\n if (typeof config !== 'object') {\n throw new Error(\n `[createResourceLinks]: \"config\" must be an object for the ${resource} resource. Received ${typeof config}`,\n );\n }\n\n if (!('label' in config)) {\n throw new Error(\n `[createResourceLinks]: \"label\" is required for the ${resource} resource.`,\n );\n }\n\n if (typeof config.label !== 'string') {\n throw new Error(\n `[createResourceLinks]: \"label\" must be a string for the ${resource} resource. Received ${typeof config.label}`,\n );\n }\n\n const linkConfig = config as CreateResourceLinkOptions<\n Resources,\n typeof resource\n >;\n\n if (\n 'href' in linkConfig &&\n linkConfig.href !== undefined &&\n typeof linkConfig.href !== 'string' &&\n typeof linkConfig.href !== 'function'\n ) {\n throw new Error(\n `[createResourceLinks]: \"href\" must be a string or function for the ${resource} resource. Received ${typeof linkConfig.href}`,\n );\n }\n\n if (\n 'hash' in linkConfig &&\n linkConfig.hash !== undefined &&\n typeof linkConfig.hash !== 'string' &&\n typeof linkConfig.hash !== 'function'\n ) {\n throw new Error(\n `[createResourceLinks]: \"hash\" must be a string or function for the ${resource} resource. Received ${typeof linkConfig.hash}`,\n );\n }\n\n const givenHref = resolveResourceLinkHref(linkConfig.href, resource, '/');\n const givenHash = resolveResourceLinkHref(\n linkConfig.hash,\n resource,\n resource,\n );\n const href = {\n given: givenHref,\n full: createFullResourceLinkHref(givenHref, givenHash),\n ...(linkConfig.hash !== undefined && !givenHref.includes('#')\n ? { hash: normalizeResourceLinkHash(givenHash) }\n : {}),\n };\n\n return {\n href,\n label: config.label,\n resource,\n icon: 'icon' in config ? config.icon : null,\n };\n });\n}\n\nfunction createResourceLinksWithGroup<\n Resources extends ReadonlyArray<ResourceDefinition>,\n>(\n isValidResource: ReturnType<typeof createIsValidResourceFn<Resources>>,\n groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>,\n) {\n if (!Array.isArray(groups)) {\n throw new Error(\n '[createResourceLinks.withGroup]: \"groups\" must be an array.',\n );\n }\n\n return groups.map((group, index) => {\n if (!group) {\n throw new Error(\n `[createResourceLinks.withGroup]: group at index ${index} is required.`,\n );\n }\n\n if (typeof group !== 'object') {\n throw new Error(\n `[createResourceLinks.withGroup]: group at index ${index} must be an object. Received ${typeof group}`,\n );\n }\n\n if (\n 'label' in group &&\n group.label !== undefined &&\n typeof group.label !== 'string'\n ) {\n throw new Error(\n `[createResourceLinks.withGroup]: \"label\" must be a string for group at index ${index}. Received ${typeof group.label}`,\n );\n }\n\n if (!('links' in group)) {\n throw new Error(\n `[createResourceLinks.withGroup]: \"links\" is required for group at index ${index}.`,\n );\n }\n\n if (\n typeof group.links !== 'object' ||\n group.links === null ||\n Array.isArray(group.links)\n ) {\n throw new Error(\n `[createResourceLinks.withGroup]: \"links\" must be an object for group at index ${index}. Received ${Array.isArray(group.links) ? 'array' : typeof group.links}`,\n );\n }\n\n return {\n label: 'label' in group ? (group.label ?? null) : null,\n icon: 'icon' in group ? group.icon : null,\n links: createResourceLinksFromConfig(isValidResource, group.links),\n };\n });\n}\n\nexport function createResourceLinksFn<\n const Resources extends ReadonlyArray<ResourceDefinition>,\n>(resources: Resources): CreateResourceLinksFn<Resources> {\n const isValidResource = createIsValidResourceFn(resources);\n\n function createResourceLinks<\n const Config extends CreateResourceLinkConfig<Resources>,\n >(config: Config) {\n return createResourceLinksFromConfig(isValidResource, config);\n }\n\n function withGroup(\n groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>,\n ) {\n return createResourceLinksWithGroup(isValidResource, groups);\n }\n\n return Object.assign(createResourceLinks, {\n withGroup,\n }) as CreateResourceLinksFn<Resources>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"create-resource-links.cjs","names":["createIsValidResourceFn"],"sources":["../../src/create-config/create-resource-links.ts"],"sourcesContent":["import { ReactNode } from 'react';\nimport {\n createIsValidResourceFn,\n type LayoutResourceKey,\n type ResourceDefinition,\n} from '../resource';\n\nexport type ResourceAnchorLinkFn<Resource extends string> = (\n resource: Resource,\n) => string;\n\nexport type ResourceLinkHref<Resource extends string> =\n | string\n | ResourceAnchorLinkFn<Resource>;\n\nexport interface CreateResourceLinkOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Resource extends LayoutResourceKey<Resources>,\n> {\n /**\n * The label of the link. This is the text that will be displayed in the link.\n */\n label: string;\n /**\n * An optional icon to register with the link. This is a headless approach, meaning you have full control\n * over the icon's rendering.\n */\n icon?: ReactNode;\n /**\n * The href of the link. By default, the href will be `\"/\"`. While you **don't** need to include a hash,\n * if you do, it will override the `hash` property (if provided).\n */\n href?: ResourceLinkHref<Resource>;\n /**\n * The hash of the link. By default, the hash will be the resource name. If you need to customize it, you can provide\n * a string or a function that returns a string.\n *\n * @remarks A `\"#\"` is not required. The generated href will include it automatically.\n */\n hash?: ResourceLinkHref<Resource>;\n}\n\nexport type CreateResourceLinkConfig<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = {\n [resource in LayoutResourceKey<Resources>]?: CreateResourceLinkOptions<\n Resources,\n resource\n >;\n};\n\nexport type InferHashFromResourceLinkHref<\n Resource extends string,\n Hash extends ResourceLinkHref<Resource>,\n> = Hash extends string\n ? Hash\n : Hash extends ResourceAnchorLinkFn<Resource>\n ? ReturnType<Hash>\n : never;\n\nexport type CreatedResourceHref = {\n /**\n * The full generated href with the `hash` if provided.\n */\n full: string;\n /**\n * The given href. This is the same value as the `href` property of the config.\n */\n given: string;\n};\n\nexport type CreatedResourceLinkBase<Resource extends string> = {\n href: CreatedResourceHref;\n label: string;\n resource: Resource;\n icon: ReactNode;\n};\nexport type CreateResourceLinkWithHash<\n Resource extends string,\n Hash extends ResourceLinkHref<Resource>,\n> = Omit<CreatedResourceLinkBase<Resource>, 'href'> & {\n href: CreatedResourceHref & {\n hash: InferHashFromResourceLinkHref<Resource, Hash>;\n };\n};\n\nexport type CreatedResourceLink<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Config extends CreateResourceLinkConfig<Resources>,\n> = {\n [Resource in keyof Config]: Resource extends LayoutResourceKey<Resources>\n ? Config[Resource] extends {\n hash: infer hash extends ResourceLinkHref<Resource>;\n }\n ? CreateResourceLinkWithHash<Resource, hash>\n : CreatedResourceLinkBase<Resource>\n : never;\n}[keyof Config];\n\nexport interface CreateResourceLinksFn<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> {\n <const Config extends CreateResourceLinkConfig<Resources>>(\n config: Config,\n ): Array<CreatedResourceLink<Resources, Config>>;\n withGroups: CreateResourceLinksWithGroupsFn<Resources>;\n}\n\nexport interface CreateResourceLinkGroupOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Links extends CreateResourceLinkConfig<Resources> =\n CreateResourceLinkConfig<Resources>,\n> {\n /**\n * The label of the group. This is the text that will be displayed for the group.\n */\n label?: string;\n /**\n * An optional icon to register with the group. This is a headless approach, meaning you have full control\n * over the icon's rendering.\n */\n icon?: ReactNode;\n /**\n * The resource links in this group.\n */\n links: Links;\n}\n\nexport type CreateResourceLinkGroupInput<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = CreateResourceLinkGroupOptions<\n Resources,\n CreateResourceLinkConfig<Resources>\n>;\n\nexport type AnyCreatedResourceLink<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = {\n [Resource in LayoutResourceKey<Resources>]:\n | CreatedResourceLinkBase<Resource>\n | CreateResourceLinkWithHash<Resource, string>;\n}[LayoutResourceKey<Resources>];\n\nexport type CreateResourceLinksWithGroups<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = {\n id: string;\n label: string | null;\n icon: ReactNode;\n links: Array<AnyCreatedResourceLink<Resources>>;\n};\n\nexport type CreateResourceLinksWithGroupsFn<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = (\n groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>,\n) => Array<CreateResourceLinksWithGroups<Resources>>;\n\nfunction resolveResourceLinkHref<Resource extends string>(\n value: ResourceLinkHref<Resource> | undefined,\n resource: Resource,\n fallback: string,\n) {\n return typeof value === 'function' ? value(resource) : (value ?? fallback);\n}\n\nfunction normalizeResourceLinkHash(hash: string) {\n return hash.replace(/^#+/, '');\n}\n\nfunction createFullResourceLinkHref(href: string, hash: string) {\n if (href.includes('#')) {\n return href;\n }\n\n return `${href}#${normalizeResourceLinkHash(hash)}`;\n}\n\nfunction createResourceLinksFromConfig<\n Resources extends ReadonlyArray<ResourceDefinition>,\n>(\n isValidResource: ReturnType<typeof createIsValidResourceFn<Resources>>,\n config: CreateResourceLinkConfig<Resources>,\n) {\n return Object.entries(config).map(([resource, config]) => {\n if (!isValidResource(resource)) {\n throw new Error(`[createResourceLinks]: Invalid resource: ${resource}`);\n }\n\n if (!config) {\n throw new Error(\n `[createResourceLinks]: \"config\" is required for the ${resource} resource.`,\n );\n }\n\n if (typeof config !== 'object') {\n throw new Error(\n `[createResourceLinks]: \"config\" must be an object for the ${resource} resource. Received ${typeof config}`,\n );\n }\n\n if (!('label' in config)) {\n throw new Error(\n `[createResourceLinks]: \"label\" is required for the ${resource} resource.`,\n );\n }\n\n if (typeof config.label !== 'string') {\n throw new Error(\n `[createResourceLinks]: \"label\" must be a string for the ${resource} resource. Received ${typeof config.label}`,\n );\n }\n\n const linkConfig = config as CreateResourceLinkOptions<\n Resources,\n typeof resource\n >;\n\n if (\n 'href' in linkConfig &&\n linkConfig.href !== undefined &&\n typeof linkConfig.href !== 'string' &&\n typeof linkConfig.href !== 'function'\n ) {\n throw new Error(\n `[createResourceLinks]: \"href\" must be a string or function for the ${resource} resource. Received ${typeof linkConfig.href}`,\n );\n }\n\n if (\n 'hash' in linkConfig &&\n linkConfig.hash !== undefined &&\n typeof linkConfig.hash !== 'string' &&\n typeof linkConfig.hash !== 'function'\n ) {\n throw new Error(\n `[createResourceLinks]: \"hash\" must be a string or function for the ${resource} resource. Received ${typeof linkConfig.hash}`,\n );\n }\n\n const givenHref = resolveResourceLinkHref(linkConfig.href, resource, '/');\n const givenHash = resolveResourceLinkHref(\n linkConfig.hash,\n resource,\n resource,\n );\n const href = {\n given: givenHref,\n full: createFullResourceLinkHref(givenHref, givenHash),\n ...(linkConfig.hash !== undefined && !givenHref.includes('#')\n ? { hash: normalizeResourceLinkHash(givenHash) }\n : {}),\n };\n\n return {\n href,\n label: config.label,\n resource,\n icon: 'icon' in config ? config.icon : null,\n };\n });\n}\n\nfunction createResourceLinkGroupId() {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n return `group-${Math.random().toString(36).slice(2, 11)}`;\n}\n\nfunction createResourceLinksWithGroups<\n Resources extends ReadonlyArray<ResourceDefinition>,\n>(\n isValidResource: ReturnType<typeof createIsValidResourceFn<Resources>>,\n groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>,\n): Array<CreateResourceLinksWithGroups<Resources>> {\n if (!Array.isArray(groups)) {\n throw new Error(\n '[createResourceLinks.withGroups]: \"groups\" must be an array.',\n );\n }\n\n return groups.map((group, index) => {\n if (!group) {\n throw new Error(\n `[createResourceLinks.withGroups]: group at index ${index} is required.`,\n );\n }\n\n if (typeof group !== 'object') {\n throw new Error(\n `[createResourceLinks.withGroups]: group at index ${index} must be an object. Received ${typeof group}`,\n );\n }\n\n if (\n 'label' in group &&\n group.label !== undefined &&\n typeof group.label !== 'string'\n ) {\n throw new Error(\n `[createResourceLinks.withGroups]: \"label\" must be a string for group at index ${index}. Received ${typeof group.label}`,\n );\n }\n\n if (!('links' in group)) {\n throw new Error(\n `[createResourceLinks.withGroups]: \"links\" is required for group at index ${index}.`,\n );\n }\n\n if (\n typeof group.links !== 'object' ||\n group.links === null ||\n Array.isArray(group.links)\n ) {\n throw new Error(\n `[createResourceLinks.withGroups]: \"links\" must be an object for group at index ${index}. Received ${Array.isArray(group.links) ? 'array' : typeof group.links}`,\n );\n }\n\n return {\n id: createResourceLinkGroupId(),\n label: 'label' in group ? (group.label ?? null) : null,\n icon: 'icon' in group ? group.icon : null,\n links: createResourceLinksFromConfig(isValidResource, group.links),\n };\n }) as Array<CreateResourceLinksWithGroups<Resources>>;\n}\n\nexport function createResourceLinksFn<\n const Resources extends ReadonlyArray<ResourceDefinition>,\n>(resources: Resources): CreateResourceLinksFn<Resources> {\n const isValidResource = createIsValidResourceFn(resources);\n\n function createResourceLinks<\n const Config extends CreateResourceLinkConfig<Resources>,\n >(config: Config) {\n return createResourceLinksFromConfig(isValidResource, config);\n }\n\n function withGroups(\n groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>,\n ) {\n return createResourceLinksWithGroups(isValidResource, groups);\n }\n\n return Object.assign(createResourceLinks, {\n withGroups,\n }) as CreateResourceLinksFn<Resources>;\n}\n"],"mappings":"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"}
|
|
@@ -55,7 +55,7 @@ type CreatedResourceLink<Resources extends ReadonlyArray<ResourceDefinition>, Co
|
|
|
55
55
|
} ? CreateResourceLinkWithHash<Resource, hash> : CreatedResourceLinkBase<Resource> : never }[keyof Config];
|
|
56
56
|
interface CreateResourceLinksFn<Resources extends ReadonlyArray<ResourceDefinition>> {
|
|
57
57
|
<const Config extends CreateResourceLinkConfig<Resources>>(config: Config): Array<CreatedResourceLink<Resources, Config>>;
|
|
58
|
-
|
|
58
|
+
withGroups: CreateResourceLinksWithGroupsFn<Resources>;
|
|
59
59
|
}
|
|
60
60
|
interface CreateResourceLinkGroupOptions<Resources extends ReadonlyArray<ResourceDefinition>, Links extends CreateResourceLinkConfig<Resources> = CreateResourceLinkConfig<Resources>> {
|
|
61
61
|
/**
|
|
@@ -73,12 +73,14 @@ interface CreateResourceLinkGroupOptions<Resources extends ReadonlyArray<Resourc
|
|
|
73
73
|
links: Links;
|
|
74
74
|
}
|
|
75
75
|
type CreateResourceLinkGroupInput<Resources extends ReadonlyArray<ResourceDefinition>> = CreateResourceLinkGroupOptions<Resources, CreateResourceLinkConfig<Resources>>;
|
|
76
|
-
type
|
|
76
|
+
type AnyCreatedResourceLink<Resources extends ReadonlyArray<ResourceDefinition>> = { [Resource in LayoutResourceKey<Resources>]: CreatedResourceLinkBase<Resource> | CreateResourceLinkWithHash<Resource, string> }[LayoutResourceKey<Resources>];
|
|
77
|
+
type CreateResourceLinksWithGroups<Resources extends ReadonlyArray<ResourceDefinition>> = {
|
|
78
|
+
id: string;
|
|
77
79
|
label: string | null;
|
|
78
80
|
icon: ReactNode;
|
|
79
|
-
links: Array<
|
|
81
|
+
links: Array<AnyCreatedResourceLink<Resources>>;
|
|
80
82
|
};
|
|
81
|
-
type
|
|
83
|
+
type CreateResourceLinksWithGroupsFn<Resources extends ReadonlyArray<ResourceDefinition>> = (groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>) => Array<CreateResourceLinksWithGroups<Resources>>;
|
|
82
84
|
//#endregion
|
|
83
|
-
export { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn,
|
|
85
|
+
export { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn, CreateResourceLinksWithGroups, CreateResourceLinksWithGroupsFn, CreatedResourceHref, CreatedResourceLink, CreatedResourceLinkBase, InferHashFromResourceLinkHref, ResourceAnchorLinkFn, ResourceLinkHref };
|
|
84
86
|
//# sourceMappingURL=create-resource-links.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-resource-links.d.cts","names":[],"sources":["../../src/create-config/create-resource-links.ts"],"mappings":";;;;KAOY,oBAAA,6BACV,QAAA,EAAU,QAAQ;AAAA,KAGR,gBAAA,qCAER,oBAAoB,CAAC,QAAA;AAAA,UAER,yBAAA,mBACG,aAAA,CAAc,kBAAA,oBACf,iBAAA,CAAkB,SAAA;EAVL;;;EAe9B,KAAA;EAdU;;;AAAQ;EAmBlB,IAAA,GAAO,SAAA;EAhBmB;;;;EAqB1B,IAAA,GAAO,gBAAA,CAAiB,QAAA;EAnBD;;AAAQ;AAEjC;;;EAwBE,IAAA,GAAO,gBAAA,CAAiB,QAAA;AAAA;AAAA,KAGd,wBAAA,mBACQ,aAAA,CAAc,kBAAA,oBAEnB,iBAAA,CAAkB,SAAA,KAAc,yBAAA,CAC3C,SAAA,EACA,QAAA;AAAA,KAIQ,6BAAA,uCAEG,gBAAA,CAAiB,QAAA,KAC5B,IAAA,kBACA,IAAA,GACA,IAAA,SAAa,oBAAA,CAAqB,QAAA,IAChC,UAAA,CAAW,IAAA;AAAA,KAGL,mBAAA;EArBc;;;EAyBxB,IAAA;EAhDA;;;EAoDA,KAAK;AAAA;AAAA,KAGK,uBAAA;EACV,IAAA,EAAM,mBAAA;EACN,KAAA;EACA,QAAA,EAAU,QAAA;EACV,IAAA,EAAM,SAAA;AAAA;AAAA,KAEI,0BAAA,uCAEG,gBAAA,CAAiB,QAAA,KAC5B,IAAA,CAAK,uBAAA,CAAwB,QAAA;EAC/B,IAAA,EAAM,mBAAA;IACJ,IAAA,EAAM,6BAAA,CAA8B,QAAA,EAAU,IAAA;EAAA;AAAA;AAAA,KAItC,mBAAA,mBACQ,aAAA,CAAc,kBAAA,kBACjB,wBAAA,CAAyB,SAAA,0BAErB,MAAA,GAAS,QAAA,SAAiB,iBAAA,CAAkB,SAAA,IAC3D,MAAA,CAAO,QAAA;EACL,IAAA,qBAAyB,gBAAA,CAAiB,QAAA;AAAA,IAE1C,0BAAA,CAA2B,QAAA,EAAU,IAAA,IACrC,uBAAA,CAAwB,QAAA,kBAExB,MAAA;AAAA,UAES,qBAAA,mBACG,aAAA,CAAc,kBAAA;EAAA,sBAEV,wBAAA,CAAyB,SAAA,GAC7C,MAAA,EAAQ,MAAA,GACP,KAAA,CAAM,mBAAA,CAAoB,SAAA,EAAW,MAAA;EACxC,
|
|
1
|
+
{"version":3,"file":"create-resource-links.d.cts","names":[],"sources":["../../src/create-config/create-resource-links.ts"],"mappings":";;;;KAOY,oBAAA,6BACV,QAAA,EAAU,QAAQ;AAAA,KAGR,gBAAA,qCAER,oBAAoB,CAAC,QAAA;AAAA,UAER,yBAAA,mBACG,aAAA,CAAc,kBAAA,oBACf,iBAAA,CAAkB,SAAA;EAVL;;;EAe9B,KAAA;EAdU;;;AAAQ;EAmBlB,IAAA,GAAO,SAAA;EAhBmB;;;;EAqB1B,IAAA,GAAO,gBAAA,CAAiB,QAAA;EAnBD;;AAAQ;AAEjC;;;EAwBE,IAAA,GAAO,gBAAA,CAAiB,QAAA;AAAA;AAAA,KAGd,wBAAA,mBACQ,aAAA,CAAc,kBAAA,oBAEnB,iBAAA,CAAkB,SAAA,KAAc,yBAAA,CAC3C,SAAA,EACA,QAAA;AAAA,KAIQ,6BAAA,uCAEG,gBAAA,CAAiB,QAAA,KAC5B,IAAA,kBACA,IAAA,GACA,IAAA,SAAa,oBAAA,CAAqB,QAAA,IAChC,UAAA,CAAW,IAAA;AAAA,KAGL,mBAAA;EArBc;;;EAyBxB,IAAA;EAhDA;;;EAoDA,KAAK;AAAA;AAAA,KAGK,uBAAA;EACV,IAAA,EAAM,mBAAA;EACN,KAAA;EACA,QAAA,EAAU,QAAA;EACV,IAAA,EAAM,SAAA;AAAA;AAAA,KAEI,0BAAA,uCAEG,gBAAA,CAAiB,QAAA,KAC5B,IAAA,CAAK,uBAAA,CAAwB,QAAA;EAC/B,IAAA,EAAM,mBAAA;IACJ,IAAA,EAAM,6BAAA,CAA8B,QAAA,EAAU,IAAA;EAAA;AAAA;AAAA,KAItC,mBAAA,mBACQ,aAAA,CAAc,kBAAA,kBACjB,wBAAA,CAAyB,SAAA,0BAErB,MAAA,GAAS,QAAA,SAAiB,iBAAA,CAAkB,SAAA,IAC3D,MAAA,CAAO,QAAA;EACL,IAAA,qBAAyB,gBAAA,CAAiB,QAAA;AAAA,IAE1C,0BAAA,CAA2B,QAAA,EAAU,IAAA,IACrC,uBAAA,CAAwB,QAAA,kBAExB,MAAA;AAAA,UAES,qBAAA,mBACG,aAAA,CAAc,kBAAA;EAAA,sBAEV,wBAAA,CAAyB,SAAA,GAC7C,MAAA,EAAQ,MAAA,GACP,KAAA,CAAM,mBAAA,CAAoB,SAAA,EAAW,MAAA;EACxC,UAAA,EAAY,+BAAA,CAAgC,SAAA;AAAA;AAAA,UAG7B,8BAAA,mBACG,aAAA,CAAc,kBAAA,iBAClB,wBAAA,CAAyB,SAAA,IACrC,wBAAA,CAAyB,SAAA;EAlEkB;;;EAuE7C,KAAA;EAzEkB;;;;EA8ElB,IAAA,GAAO,SAAA;EA5EsC;;;EAgF7C,KAAA,EAAO,KAAA;AAAA;AAAA,KAGG,4BAAA,mBACQ,aAAA,CAAc,kBAAA,KAC9B,8BAAA,CACF,SAAA,EACA,wBAAA,CAAyB,SAAA;AAAA,KAGf,sBAAA,mBACQ,aAAA,CAAc,kBAAA,oBAEnB,iBAAA,CAAkB,SAAA,IAC3B,uBAAA,CAAwB,QAAA,IACxB,0BAAA,CAA2B,QAAA,YAC/B,iBAAA,CAAkB,SAAA;AAAA,KAER,6BAAA,mBACQ,aAAA,CAAc,kBAAA;EAEhC,EAAA;EACA,KAAA;EACA,IAAA,EAAM,SAAA;EACN,KAAA,EAAO,KAAA,CAAM,sBAAA,CAAuB,SAAA;AAAA;AAAA,KAG1B,+BAAA,mBACQ,aAAA,CAAc,kBAAA,MAEhC,MAAA,EAAQ,aAAA,CAAc,4BAAA,CAA6B,SAAA,OAChD,KAAA,CAAM,6BAAA,CAA8B,SAAA"}
|
|
@@ -55,7 +55,7 @@ type CreatedResourceLink<Resources extends ReadonlyArray<ResourceDefinition>, Co
|
|
|
55
55
|
} ? CreateResourceLinkWithHash<Resource, hash> : CreatedResourceLinkBase<Resource> : never }[keyof Config];
|
|
56
56
|
interface CreateResourceLinksFn<Resources extends ReadonlyArray<ResourceDefinition>> {
|
|
57
57
|
<const Config extends CreateResourceLinkConfig<Resources>>(config: Config): Array<CreatedResourceLink<Resources, Config>>;
|
|
58
|
-
|
|
58
|
+
withGroups: CreateResourceLinksWithGroupsFn<Resources>;
|
|
59
59
|
}
|
|
60
60
|
interface CreateResourceLinkGroupOptions<Resources extends ReadonlyArray<ResourceDefinition>, Links extends CreateResourceLinkConfig<Resources> = CreateResourceLinkConfig<Resources>> {
|
|
61
61
|
/**
|
|
@@ -73,12 +73,14 @@ interface CreateResourceLinkGroupOptions<Resources extends ReadonlyArray<Resourc
|
|
|
73
73
|
links: Links;
|
|
74
74
|
}
|
|
75
75
|
type CreateResourceLinkGroupInput<Resources extends ReadonlyArray<ResourceDefinition>> = CreateResourceLinkGroupOptions<Resources, CreateResourceLinkConfig<Resources>>;
|
|
76
|
-
type
|
|
76
|
+
type AnyCreatedResourceLink<Resources extends ReadonlyArray<ResourceDefinition>> = { [Resource in LayoutResourceKey<Resources>]: CreatedResourceLinkBase<Resource> | CreateResourceLinkWithHash<Resource, string> }[LayoutResourceKey<Resources>];
|
|
77
|
+
type CreateResourceLinksWithGroups<Resources extends ReadonlyArray<ResourceDefinition>> = {
|
|
78
|
+
id: string;
|
|
77
79
|
label: string | null;
|
|
78
80
|
icon: ReactNode;
|
|
79
|
-
links: Array<
|
|
81
|
+
links: Array<AnyCreatedResourceLink<Resources>>;
|
|
80
82
|
};
|
|
81
|
-
type
|
|
83
|
+
type CreateResourceLinksWithGroupsFn<Resources extends ReadonlyArray<ResourceDefinition>> = (groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>) => Array<CreateResourceLinksWithGroups<Resources>>;
|
|
82
84
|
//#endregion
|
|
83
|
-
export { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn,
|
|
85
|
+
export { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn, CreateResourceLinksWithGroups, CreateResourceLinksWithGroupsFn, CreatedResourceHref, CreatedResourceLink, CreatedResourceLinkBase, InferHashFromResourceLinkHref, ResourceAnchorLinkFn, ResourceLinkHref };
|
|
84
86
|
//# sourceMappingURL=create-resource-links.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-resource-links.d.mts","names":[],"sources":["../../src/create-config/create-resource-links.ts"],"mappings":";;;;KAOY,oBAAA,6BACV,QAAA,EAAU,QAAQ;AAAA,KAGR,gBAAA,qCAER,oBAAoB,CAAC,QAAA;AAAA,UAER,yBAAA,mBACG,aAAA,CAAc,kBAAA,oBACf,iBAAA,CAAkB,SAAA;EAVL;;;EAe9B,KAAA;EAdU;;;AAAQ;EAmBlB,IAAA,GAAO,SAAA;EAhBmB;;;;EAqB1B,IAAA,GAAO,gBAAA,CAAiB,QAAA;EAnBD;;AAAQ;AAEjC;;;EAwBE,IAAA,GAAO,gBAAA,CAAiB,QAAA;AAAA;AAAA,KAGd,wBAAA,mBACQ,aAAA,CAAc,kBAAA,oBAEnB,iBAAA,CAAkB,SAAA,KAAc,yBAAA,CAC3C,SAAA,EACA,QAAA;AAAA,KAIQ,6BAAA,uCAEG,gBAAA,CAAiB,QAAA,KAC5B,IAAA,kBACA,IAAA,GACA,IAAA,SAAa,oBAAA,CAAqB,QAAA,IAChC,UAAA,CAAW,IAAA;AAAA,KAGL,mBAAA;EArBc;;;EAyBxB,IAAA;EAhDA;;;EAoDA,KAAK;AAAA;AAAA,KAGK,uBAAA;EACV,IAAA,EAAM,mBAAA;EACN,KAAA;EACA,QAAA,EAAU,QAAA;EACV,IAAA,EAAM,SAAA;AAAA;AAAA,KAEI,0BAAA,uCAEG,gBAAA,CAAiB,QAAA,KAC5B,IAAA,CAAK,uBAAA,CAAwB,QAAA;EAC/B,IAAA,EAAM,mBAAA;IACJ,IAAA,EAAM,6BAAA,CAA8B,QAAA,EAAU,IAAA;EAAA;AAAA;AAAA,KAItC,mBAAA,mBACQ,aAAA,CAAc,kBAAA,kBACjB,wBAAA,CAAyB,SAAA,0BAErB,MAAA,GAAS,QAAA,SAAiB,iBAAA,CAAkB,SAAA,IAC3D,MAAA,CAAO,QAAA;EACL,IAAA,qBAAyB,gBAAA,CAAiB,QAAA;AAAA,IAE1C,0BAAA,CAA2B,QAAA,EAAU,IAAA,IACrC,uBAAA,CAAwB,QAAA,kBAExB,MAAA;AAAA,UAES,qBAAA,mBACG,aAAA,CAAc,kBAAA;EAAA,sBAEV,wBAAA,CAAyB,SAAA,GAC7C,MAAA,EAAQ,MAAA,GACP,KAAA,CAAM,mBAAA,CAAoB,SAAA,EAAW,MAAA;EACxC,
|
|
1
|
+
{"version":3,"file":"create-resource-links.d.mts","names":[],"sources":["../../src/create-config/create-resource-links.ts"],"mappings":";;;;KAOY,oBAAA,6BACV,QAAA,EAAU,QAAQ;AAAA,KAGR,gBAAA,qCAER,oBAAoB,CAAC,QAAA;AAAA,UAER,yBAAA,mBACG,aAAA,CAAc,kBAAA,oBACf,iBAAA,CAAkB,SAAA;EAVL;;;EAe9B,KAAA;EAdU;;;AAAQ;EAmBlB,IAAA,GAAO,SAAA;EAhBmB;;;;EAqB1B,IAAA,GAAO,gBAAA,CAAiB,QAAA;EAnBD;;AAAQ;AAEjC;;;EAwBE,IAAA,GAAO,gBAAA,CAAiB,QAAA;AAAA;AAAA,KAGd,wBAAA,mBACQ,aAAA,CAAc,kBAAA,oBAEnB,iBAAA,CAAkB,SAAA,KAAc,yBAAA,CAC3C,SAAA,EACA,QAAA;AAAA,KAIQ,6BAAA,uCAEG,gBAAA,CAAiB,QAAA,KAC5B,IAAA,kBACA,IAAA,GACA,IAAA,SAAa,oBAAA,CAAqB,QAAA,IAChC,UAAA,CAAW,IAAA;AAAA,KAGL,mBAAA;EArBc;;;EAyBxB,IAAA;EAhDA;;;EAoDA,KAAK;AAAA;AAAA,KAGK,uBAAA;EACV,IAAA,EAAM,mBAAA;EACN,KAAA;EACA,QAAA,EAAU,QAAA;EACV,IAAA,EAAM,SAAA;AAAA;AAAA,KAEI,0BAAA,uCAEG,gBAAA,CAAiB,QAAA,KAC5B,IAAA,CAAK,uBAAA,CAAwB,QAAA;EAC/B,IAAA,EAAM,mBAAA;IACJ,IAAA,EAAM,6BAAA,CAA8B,QAAA,EAAU,IAAA;EAAA;AAAA;AAAA,KAItC,mBAAA,mBACQ,aAAA,CAAc,kBAAA,kBACjB,wBAAA,CAAyB,SAAA,0BAErB,MAAA,GAAS,QAAA,SAAiB,iBAAA,CAAkB,SAAA,IAC3D,MAAA,CAAO,QAAA;EACL,IAAA,qBAAyB,gBAAA,CAAiB,QAAA;AAAA,IAE1C,0BAAA,CAA2B,QAAA,EAAU,IAAA,IACrC,uBAAA,CAAwB,QAAA,kBAExB,MAAA;AAAA,UAES,qBAAA,mBACG,aAAA,CAAc,kBAAA;EAAA,sBAEV,wBAAA,CAAyB,SAAA,GAC7C,MAAA,EAAQ,MAAA,GACP,KAAA,CAAM,mBAAA,CAAoB,SAAA,EAAW,MAAA;EACxC,UAAA,EAAY,+BAAA,CAAgC,SAAA;AAAA;AAAA,UAG7B,8BAAA,mBACG,aAAA,CAAc,kBAAA,iBAClB,wBAAA,CAAyB,SAAA,IACrC,wBAAA,CAAyB,SAAA;EAlEkB;;;EAuE7C,KAAA;EAzEkB;;;;EA8ElB,IAAA,GAAO,SAAA;EA5EsC;;;EAgF7C,KAAA,EAAO,KAAA;AAAA;AAAA,KAGG,4BAAA,mBACQ,aAAA,CAAc,kBAAA,KAC9B,8BAAA,CACF,SAAA,EACA,wBAAA,CAAyB,SAAA;AAAA,KAGf,sBAAA,mBACQ,aAAA,CAAc,kBAAA,oBAEnB,iBAAA,CAAkB,SAAA,IAC3B,uBAAA,CAAwB,QAAA,IACxB,0BAAA,CAA2B,QAAA,YAC/B,iBAAA,CAAkB,SAAA;AAAA,KAER,6BAAA,mBACQ,aAAA,CAAc,kBAAA;EAEhC,EAAA;EACA,KAAA;EACA,IAAA,EAAM,SAAA;EACN,KAAA,EAAO,KAAA,CAAM,sBAAA,CAAuB,SAAA;AAAA;AAAA,KAG1B,+BAAA,mBACQ,aAAA,CAAc,kBAAA,MAEhC,MAAA,EAAQ,aAAA,CAAc,4BAAA,CAA6B,SAAA,OAChD,KAAA,CAAM,6BAAA,CAA8B,SAAA"}
|
|
@@ -35,15 +35,20 @@ function createResourceLinksFromConfig(isValidResource, config) {
|
|
|
35
35
|
};
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
-
function
|
|
39
|
-
if (
|
|
38
|
+
function createResourceLinkGroupId() {
|
|
39
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
40
|
+
return `group-${Math.random().toString(36).slice(2, 11)}`;
|
|
41
|
+
}
|
|
42
|
+
function createResourceLinksWithGroups(isValidResource, groups) {
|
|
43
|
+
if (!Array.isArray(groups)) throw new Error("[createResourceLinks.withGroups]: \"groups\" must be an array.");
|
|
40
44
|
return groups.map((group, index) => {
|
|
41
|
-
if (!group) throw new Error(`[createResourceLinks.
|
|
42
|
-
if (typeof group !== "object") throw new Error(`[createResourceLinks.
|
|
43
|
-
if ("label" in group && group.label !== void 0 && typeof group.label !== "string") throw new Error(`[createResourceLinks.
|
|
44
|
-
if (!("links" in group)) throw new Error(`[createResourceLinks.
|
|
45
|
-
if (typeof group.links !== "object" || group.links === null || Array.isArray(group.links)) throw new Error(`[createResourceLinks.
|
|
45
|
+
if (!group) throw new Error(`[createResourceLinks.withGroups]: group at index ${index} is required.`);
|
|
46
|
+
if (typeof group !== "object") throw new Error(`[createResourceLinks.withGroups]: group at index ${index} must be an object. Received ${typeof group}`);
|
|
47
|
+
if ("label" in group && group.label !== void 0 && typeof group.label !== "string") throw new Error(`[createResourceLinks.withGroups]: "label" must be a string for group at index ${index}. Received ${typeof group.label}`);
|
|
48
|
+
if (!("links" in group)) throw new Error(`[createResourceLinks.withGroups]: "links" is required for group at index ${index}.`);
|
|
49
|
+
if (typeof group.links !== "object" || group.links === null || Array.isArray(group.links)) throw new Error(`[createResourceLinks.withGroups]: "links" must be an object for group at index ${index}. Received ${Array.isArray(group.links) ? "array" : typeof group.links}`);
|
|
46
50
|
return {
|
|
51
|
+
id: createResourceLinkGroupId(),
|
|
47
52
|
label: "label" in group ? group.label ?? null : null,
|
|
48
53
|
icon: "icon" in group ? group.icon : null,
|
|
49
54
|
links: createResourceLinksFromConfig(isValidResource, group.links)
|
|
@@ -55,10 +60,10 @@ function createResourceLinksFn(resources) {
|
|
|
55
60
|
function createResourceLinks(config) {
|
|
56
61
|
return createResourceLinksFromConfig(isValidResource, config);
|
|
57
62
|
}
|
|
58
|
-
function
|
|
59
|
-
return
|
|
63
|
+
function withGroups(groups) {
|
|
64
|
+
return createResourceLinksWithGroups(isValidResource, groups);
|
|
60
65
|
}
|
|
61
|
-
return Object.assign(createResourceLinks, {
|
|
66
|
+
return Object.assign(createResourceLinks, { withGroups });
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-resource-links.mjs","names":[],"sources":["../../src/create-config/create-resource-links.ts"],"sourcesContent":["import { ReactNode } from 'react';\nimport {\n createIsValidResourceFn,\n type LayoutResourceKey,\n type ResourceDefinition,\n} from '../resource';\n\nexport type ResourceAnchorLinkFn<Resource extends string> = (\n resource: Resource,\n) => string;\n\nexport type ResourceLinkHref<Resource extends string> =\n | string\n | ResourceAnchorLinkFn<Resource>;\n\nexport interface CreateResourceLinkOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Resource extends LayoutResourceKey<Resources>,\n> {\n /**\n * The label of the link. This is the text that will be displayed in the link.\n */\n label: string;\n /**\n * An optional icon to register with the link. This is a headless approach, meaning you have full control\n * over the icon's rendering.\n */\n icon?: ReactNode;\n /**\n * The href of the link. By default, the href will be `\"/\"`. While you **don't** need to include a hash,\n * if you do, it will override the `hash` property (if provided).\n */\n href?: ResourceLinkHref<Resource>;\n /**\n * The hash of the link. By default, the hash will be the resource name. If you need to customize it, you can provide\n * a string or a function that returns a string.\n *\n * @remarks A `\"#\"` is not required. The generated href will include it automatically.\n */\n hash?: ResourceLinkHref<Resource>;\n}\n\nexport type CreateResourceLinkConfig<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = {\n [resource in LayoutResourceKey<Resources>]?: CreateResourceLinkOptions<\n Resources,\n resource\n >;\n};\n\nexport type InferHashFromResourceLinkHref<\n Resource extends string,\n Hash extends ResourceLinkHref<Resource>,\n> = Hash extends string\n ? Hash\n : Hash extends ResourceAnchorLinkFn<Resource>\n ? ReturnType<Hash>\n : never;\n\nexport type CreatedResourceHref = {\n /**\n * The full generated href with the `hash` if provided.\n */\n full: string;\n /**\n * The given href. This is the same value as the `href` property of the config.\n */\n given: string;\n};\n\nexport type CreatedResourceLinkBase<Resource extends string> = {\n href: CreatedResourceHref;\n label: string;\n resource: Resource;\n icon: ReactNode;\n};\nexport type CreateResourceLinkWithHash<\n Resource extends string,\n Hash extends ResourceLinkHref<Resource>,\n> = Omit<CreatedResourceLinkBase<Resource>, 'href'> & {\n href: CreatedResourceHref & {\n hash: InferHashFromResourceLinkHref<Resource, Hash>;\n };\n};\n\nexport type CreatedResourceLink<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Config extends CreateResourceLinkConfig<Resources>,\n> = {\n [Resource in keyof Config]: Resource extends LayoutResourceKey<Resources>\n ? Config[Resource] extends {\n hash: infer hash extends ResourceLinkHref<Resource>;\n }\n ? CreateResourceLinkWithHash<Resource, hash>\n : CreatedResourceLinkBase<Resource>\n : never;\n}[keyof Config];\n\nexport interface CreateResourceLinksFn<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> {\n <const Config extends CreateResourceLinkConfig<Resources>>(\n config: Config,\n ): Array<CreatedResourceLink<Resources, Config>>;\n withGroup: CreateResourceLinksWithGroupFn<Resources>;\n}\n\nexport interface CreateResourceLinkGroupOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Links extends CreateResourceLinkConfig<Resources> =\n CreateResourceLinkConfig<Resources>,\n> {\n /**\n * The label of the group. This is the text that will be displayed for the group.\n */\n label?: string;\n /**\n * An optional icon to register with the group. This is a headless approach, meaning you have full control\n * over the icon's rendering.\n */\n icon?: ReactNode;\n /**\n * The resource links in this group.\n */\n links: Links;\n}\n\nexport type CreateResourceLinkGroupInput<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = CreateResourceLinkGroupOptions<\n Resources,\n CreateResourceLinkConfig<Resources>\n>;\n\nexport type CreateResourceLinksWithGroups<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Links extends CreateResourceLinkConfig<Resources>,\n> = {\n label: string | null;\n icon: ReactNode;\n links: Array<CreatedResourceLink<Resources, Links>>;\n};\n\nexport type CreateResourceLinksWithGroupFn<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = <Groups extends ReadonlyArray<CreateResourceLinkGroupInput<Resources>>>(\n groups: Groups,\n) => Array<\n Groups[number] extends CreateResourceLinkGroupOptions<Resources, infer Links>\n ? CreateResourceLinksWithGroups<Resources, Links>\n : CreateResourceLinksWithGroups<\n Resources,\n CreateResourceLinkConfig<Resources>\n >\n>;\n\nfunction resolveResourceLinkHref<Resource extends string>(\n value: ResourceLinkHref<Resource> | undefined,\n resource: Resource,\n fallback: string,\n) {\n return typeof value === 'function' ? value(resource) : (value ?? fallback);\n}\n\nfunction normalizeResourceLinkHash(hash: string) {\n return hash.replace(/^#+/, '');\n}\n\nfunction createFullResourceLinkHref(href: string, hash: string) {\n if (href.includes('#')) {\n return href;\n }\n\n return `${href}#${normalizeResourceLinkHash(hash)}`;\n}\n\nfunction createResourceLinksFromConfig<\n Resources extends ReadonlyArray<ResourceDefinition>,\n>(\n isValidResource: ReturnType<typeof createIsValidResourceFn<Resources>>,\n config: CreateResourceLinkConfig<Resources>,\n) {\n return Object.entries(config).map(([resource, config]) => {\n if (!isValidResource(resource)) {\n throw new Error(`[createResourceLinks]: Invalid resource: ${resource}`);\n }\n\n if (!config) {\n throw new Error(\n `[createResourceLinks]: \"config\" is required for the ${resource} resource.`,\n );\n }\n\n if (typeof config !== 'object') {\n throw new Error(\n `[createResourceLinks]: \"config\" must be an object for the ${resource} resource. Received ${typeof config}`,\n );\n }\n\n if (!('label' in config)) {\n throw new Error(\n `[createResourceLinks]: \"label\" is required for the ${resource} resource.`,\n );\n }\n\n if (typeof config.label !== 'string') {\n throw new Error(\n `[createResourceLinks]: \"label\" must be a string for the ${resource} resource. Received ${typeof config.label}`,\n );\n }\n\n const linkConfig = config as CreateResourceLinkOptions<\n Resources,\n typeof resource\n >;\n\n if (\n 'href' in linkConfig &&\n linkConfig.href !== undefined &&\n typeof linkConfig.href !== 'string' &&\n typeof linkConfig.href !== 'function'\n ) {\n throw new Error(\n `[createResourceLinks]: \"href\" must be a string or function for the ${resource} resource. Received ${typeof linkConfig.href}`,\n );\n }\n\n if (\n 'hash' in linkConfig &&\n linkConfig.hash !== undefined &&\n typeof linkConfig.hash !== 'string' &&\n typeof linkConfig.hash !== 'function'\n ) {\n throw new Error(\n `[createResourceLinks]: \"hash\" must be a string or function for the ${resource} resource. Received ${typeof linkConfig.hash}`,\n );\n }\n\n const givenHref = resolveResourceLinkHref(linkConfig.href, resource, '/');\n const givenHash = resolveResourceLinkHref(\n linkConfig.hash,\n resource,\n resource,\n );\n const href = {\n given: givenHref,\n full: createFullResourceLinkHref(givenHref, givenHash),\n ...(linkConfig.hash !== undefined && !givenHref.includes('#')\n ? { hash: normalizeResourceLinkHash(givenHash) }\n : {}),\n };\n\n return {\n href,\n label: config.label,\n resource,\n icon: 'icon' in config ? config.icon : null,\n };\n });\n}\n\nfunction createResourceLinksWithGroup<\n Resources extends ReadonlyArray<ResourceDefinition>,\n>(\n isValidResource: ReturnType<typeof createIsValidResourceFn<Resources>>,\n groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>,\n) {\n if (!Array.isArray(groups)) {\n throw new Error(\n '[createResourceLinks.withGroup]: \"groups\" must be an array.',\n );\n }\n\n return groups.map((group, index) => {\n if (!group) {\n throw new Error(\n `[createResourceLinks.withGroup]: group at index ${index} is required.`,\n );\n }\n\n if (typeof group !== 'object') {\n throw new Error(\n `[createResourceLinks.withGroup]: group at index ${index} must be an object. Received ${typeof group}`,\n );\n }\n\n if (\n 'label' in group &&\n group.label !== undefined &&\n typeof group.label !== 'string'\n ) {\n throw new Error(\n `[createResourceLinks.withGroup]: \"label\" must be a string for group at index ${index}. Received ${typeof group.label}`,\n );\n }\n\n if (!('links' in group)) {\n throw new Error(\n `[createResourceLinks.withGroup]: \"links\" is required for group at index ${index}.`,\n );\n }\n\n if (\n typeof group.links !== 'object' ||\n group.links === null ||\n Array.isArray(group.links)\n ) {\n throw new Error(\n `[createResourceLinks.withGroup]: \"links\" must be an object for group at index ${index}. Received ${Array.isArray(group.links) ? 'array' : typeof group.links}`,\n );\n }\n\n return {\n label: 'label' in group ? (group.label ?? null) : null,\n icon: 'icon' in group ? group.icon : null,\n links: createResourceLinksFromConfig(isValidResource, group.links),\n };\n });\n}\n\nexport function createResourceLinksFn<\n const Resources extends ReadonlyArray<ResourceDefinition>,\n>(resources: Resources): CreateResourceLinksFn<Resources> {\n const isValidResource = createIsValidResourceFn(resources);\n\n function createResourceLinks<\n const Config extends CreateResourceLinkConfig<Resources>,\n >(config: Config) {\n return createResourceLinksFromConfig(isValidResource, config);\n }\n\n function withGroup(\n groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>,\n ) {\n return createResourceLinksWithGroup(isValidResource, groups);\n }\n\n return Object.assign(createResourceLinks, {\n withGroup,\n }) as CreateResourceLinksFn<Resources>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"create-resource-links.mjs","names":[],"sources":["../../src/create-config/create-resource-links.ts"],"sourcesContent":["import { ReactNode } from 'react';\nimport {\n createIsValidResourceFn,\n type LayoutResourceKey,\n type ResourceDefinition,\n} from '../resource';\n\nexport type ResourceAnchorLinkFn<Resource extends string> = (\n resource: Resource,\n) => string;\n\nexport type ResourceLinkHref<Resource extends string> =\n | string\n | ResourceAnchorLinkFn<Resource>;\n\nexport interface CreateResourceLinkOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Resource extends LayoutResourceKey<Resources>,\n> {\n /**\n * The label of the link. This is the text that will be displayed in the link.\n */\n label: string;\n /**\n * An optional icon to register with the link. This is a headless approach, meaning you have full control\n * over the icon's rendering.\n */\n icon?: ReactNode;\n /**\n * The href of the link. By default, the href will be `\"/\"`. While you **don't** need to include a hash,\n * if you do, it will override the `hash` property (if provided).\n */\n href?: ResourceLinkHref<Resource>;\n /**\n * The hash of the link. By default, the hash will be the resource name. If you need to customize it, you can provide\n * a string or a function that returns a string.\n *\n * @remarks A `\"#\"` is not required. The generated href will include it automatically.\n */\n hash?: ResourceLinkHref<Resource>;\n}\n\nexport type CreateResourceLinkConfig<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = {\n [resource in LayoutResourceKey<Resources>]?: CreateResourceLinkOptions<\n Resources,\n resource\n >;\n};\n\nexport type InferHashFromResourceLinkHref<\n Resource extends string,\n Hash extends ResourceLinkHref<Resource>,\n> = Hash extends string\n ? Hash\n : Hash extends ResourceAnchorLinkFn<Resource>\n ? ReturnType<Hash>\n : never;\n\nexport type CreatedResourceHref = {\n /**\n * The full generated href with the `hash` if provided.\n */\n full: string;\n /**\n * The given href. This is the same value as the `href` property of the config.\n */\n given: string;\n};\n\nexport type CreatedResourceLinkBase<Resource extends string> = {\n href: CreatedResourceHref;\n label: string;\n resource: Resource;\n icon: ReactNode;\n};\nexport type CreateResourceLinkWithHash<\n Resource extends string,\n Hash extends ResourceLinkHref<Resource>,\n> = Omit<CreatedResourceLinkBase<Resource>, 'href'> & {\n href: CreatedResourceHref & {\n hash: InferHashFromResourceLinkHref<Resource, Hash>;\n };\n};\n\nexport type CreatedResourceLink<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Config extends CreateResourceLinkConfig<Resources>,\n> = {\n [Resource in keyof Config]: Resource extends LayoutResourceKey<Resources>\n ? Config[Resource] extends {\n hash: infer hash extends ResourceLinkHref<Resource>;\n }\n ? CreateResourceLinkWithHash<Resource, hash>\n : CreatedResourceLinkBase<Resource>\n : never;\n}[keyof Config];\n\nexport interface CreateResourceLinksFn<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> {\n <const Config extends CreateResourceLinkConfig<Resources>>(\n config: Config,\n ): Array<CreatedResourceLink<Resources, Config>>;\n withGroups: CreateResourceLinksWithGroupsFn<Resources>;\n}\n\nexport interface CreateResourceLinkGroupOptions<\n Resources extends ReadonlyArray<ResourceDefinition>,\n Links extends CreateResourceLinkConfig<Resources> =\n CreateResourceLinkConfig<Resources>,\n> {\n /**\n * The label of the group. This is the text that will be displayed for the group.\n */\n label?: string;\n /**\n * An optional icon to register with the group. This is a headless approach, meaning you have full control\n * over the icon's rendering.\n */\n icon?: ReactNode;\n /**\n * The resource links in this group.\n */\n links: Links;\n}\n\nexport type CreateResourceLinkGroupInput<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = CreateResourceLinkGroupOptions<\n Resources,\n CreateResourceLinkConfig<Resources>\n>;\n\nexport type AnyCreatedResourceLink<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = {\n [Resource in LayoutResourceKey<Resources>]:\n | CreatedResourceLinkBase<Resource>\n | CreateResourceLinkWithHash<Resource, string>;\n}[LayoutResourceKey<Resources>];\n\nexport type CreateResourceLinksWithGroups<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = {\n id: string;\n label: string | null;\n icon: ReactNode;\n links: Array<AnyCreatedResourceLink<Resources>>;\n};\n\nexport type CreateResourceLinksWithGroupsFn<\n Resources extends ReadonlyArray<ResourceDefinition>,\n> = (\n groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>,\n) => Array<CreateResourceLinksWithGroups<Resources>>;\n\nfunction resolveResourceLinkHref<Resource extends string>(\n value: ResourceLinkHref<Resource> | undefined,\n resource: Resource,\n fallback: string,\n) {\n return typeof value === 'function' ? value(resource) : (value ?? fallback);\n}\n\nfunction normalizeResourceLinkHash(hash: string) {\n return hash.replace(/^#+/, '');\n}\n\nfunction createFullResourceLinkHref(href: string, hash: string) {\n if (href.includes('#')) {\n return href;\n }\n\n return `${href}#${normalizeResourceLinkHash(hash)}`;\n}\n\nfunction createResourceLinksFromConfig<\n Resources extends ReadonlyArray<ResourceDefinition>,\n>(\n isValidResource: ReturnType<typeof createIsValidResourceFn<Resources>>,\n config: CreateResourceLinkConfig<Resources>,\n) {\n return Object.entries(config).map(([resource, config]) => {\n if (!isValidResource(resource)) {\n throw new Error(`[createResourceLinks]: Invalid resource: ${resource}`);\n }\n\n if (!config) {\n throw new Error(\n `[createResourceLinks]: \"config\" is required for the ${resource} resource.`,\n );\n }\n\n if (typeof config !== 'object') {\n throw new Error(\n `[createResourceLinks]: \"config\" must be an object for the ${resource} resource. Received ${typeof config}`,\n );\n }\n\n if (!('label' in config)) {\n throw new Error(\n `[createResourceLinks]: \"label\" is required for the ${resource} resource.`,\n );\n }\n\n if (typeof config.label !== 'string') {\n throw new Error(\n `[createResourceLinks]: \"label\" must be a string for the ${resource} resource. Received ${typeof config.label}`,\n );\n }\n\n const linkConfig = config as CreateResourceLinkOptions<\n Resources,\n typeof resource\n >;\n\n if (\n 'href' in linkConfig &&\n linkConfig.href !== undefined &&\n typeof linkConfig.href !== 'string' &&\n typeof linkConfig.href !== 'function'\n ) {\n throw new Error(\n `[createResourceLinks]: \"href\" must be a string or function for the ${resource} resource. Received ${typeof linkConfig.href}`,\n );\n }\n\n if (\n 'hash' in linkConfig &&\n linkConfig.hash !== undefined &&\n typeof linkConfig.hash !== 'string' &&\n typeof linkConfig.hash !== 'function'\n ) {\n throw new Error(\n `[createResourceLinks]: \"hash\" must be a string or function for the ${resource} resource. Received ${typeof linkConfig.hash}`,\n );\n }\n\n const givenHref = resolveResourceLinkHref(linkConfig.href, resource, '/');\n const givenHash = resolveResourceLinkHref(\n linkConfig.hash,\n resource,\n resource,\n );\n const href = {\n given: givenHref,\n full: createFullResourceLinkHref(givenHref, givenHash),\n ...(linkConfig.hash !== undefined && !givenHref.includes('#')\n ? { hash: normalizeResourceLinkHash(givenHash) }\n : {}),\n };\n\n return {\n href,\n label: config.label,\n resource,\n icon: 'icon' in config ? config.icon : null,\n };\n });\n}\n\nfunction createResourceLinkGroupId() {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n return `group-${Math.random().toString(36).slice(2, 11)}`;\n}\n\nfunction createResourceLinksWithGroups<\n Resources extends ReadonlyArray<ResourceDefinition>,\n>(\n isValidResource: ReturnType<typeof createIsValidResourceFn<Resources>>,\n groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>,\n): Array<CreateResourceLinksWithGroups<Resources>> {\n if (!Array.isArray(groups)) {\n throw new Error(\n '[createResourceLinks.withGroups]: \"groups\" must be an array.',\n );\n }\n\n return groups.map((group, index) => {\n if (!group) {\n throw new Error(\n `[createResourceLinks.withGroups]: group at index ${index} is required.`,\n );\n }\n\n if (typeof group !== 'object') {\n throw new Error(\n `[createResourceLinks.withGroups]: group at index ${index} must be an object. Received ${typeof group}`,\n );\n }\n\n if (\n 'label' in group &&\n group.label !== undefined &&\n typeof group.label !== 'string'\n ) {\n throw new Error(\n `[createResourceLinks.withGroups]: \"label\" must be a string for group at index ${index}. Received ${typeof group.label}`,\n );\n }\n\n if (!('links' in group)) {\n throw new Error(\n `[createResourceLinks.withGroups]: \"links\" is required for group at index ${index}.`,\n );\n }\n\n if (\n typeof group.links !== 'object' ||\n group.links === null ||\n Array.isArray(group.links)\n ) {\n throw new Error(\n `[createResourceLinks.withGroups]: \"links\" must be an object for group at index ${index}. Received ${Array.isArray(group.links) ? 'array' : typeof group.links}`,\n );\n }\n\n return {\n id: createResourceLinkGroupId(),\n label: 'label' in group ? (group.label ?? null) : null,\n icon: 'icon' in group ? group.icon : null,\n links: createResourceLinksFromConfig(isValidResource, group.links),\n };\n }) as Array<CreateResourceLinksWithGroups<Resources>>;\n}\n\nexport function createResourceLinksFn<\n const Resources extends ReadonlyArray<ResourceDefinition>,\n>(resources: Resources): CreateResourceLinksFn<Resources> {\n const isValidResource = createIsValidResourceFn(resources);\n\n function createResourceLinks<\n const Config extends CreateResourceLinkConfig<Resources>,\n >(config: Config) {\n return createResourceLinksFromConfig(isValidResource, config);\n }\n\n function withGroups(\n groups: ReadonlyArray<CreateResourceLinkGroupInput<Resources>>,\n ) {\n return createResourceLinksWithGroups(isValidResource, groups);\n }\n\n return Object.assign(createResourceLinks, {\n withGroups,\n }) as CreateResourceLinksFn<Resources>;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { BaseResourceConfigComponents, ResourceConfig, ResourceConfigComponentKey, ResourceConfigComponents, ResourceConfigInput, ResourceConfigMap, SharedResourceConfigOptions, SubResourceConfig, SubResourceConfigComponentsFor } from "./types.cjs";
|
|
2
2
|
import { CreateResourceConfigFn, CreatedResourceConfig, GetComponent, GetComponentAtBound, GetComponentForResource, GetComponentForResourceOptions, GetComponentOptions, GetComponentOptionsForResource, ResourceFromGetComponentBound, SubResourceFromGetComponentBound, ValidateForResourceBound } from "./get-component.cjs";
|
|
3
|
-
import { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn,
|
|
3
|
+
import { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn, CreateResourceLinksWithGroups, CreateResourceLinksWithGroupsFn, CreatedResourceHref, CreatedResourceLink, CreatedResourceLinkBase, InferHashFromResourceLinkHref, ResourceAnchorLinkFn, ResourceLinkHref } from "./create-resource-links.cjs";
|
|
4
4
|
import { CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, defineResourceLayout } from "./define-layout.cjs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { BaseResourceConfigComponents, ResourceConfig, ResourceConfigComponentKey, ResourceConfigComponents, ResourceConfigInput, ResourceConfigMap, SharedResourceConfigOptions, SubResourceConfig, SubResourceConfigComponentsFor } from "./types.mjs";
|
|
2
2
|
import { CreateResourceConfigFn, CreatedResourceConfig, GetComponent, GetComponentAtBound, GetComponentForResource, GetComponentForResourceOptions, GetComponentOptions, GetComponentOptionsForResource, ResourceFromGetComponentBound, SubResourceFromGetComponentBound, ValidateForResourceBound } from "./get-component.mjs";
|
|
3
|
-
import { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn,
|
|
3
|
+
import { CreateResourceLinkConfig, CreateResourceLinkGroupInput, CreateResourceLinkGroupOptions, CreateResourceLinkOptions, CreateResourceLinksFn, CreateResourceLinksWithGroups, CreateResourceLinksWithGroupsFn, CreatedResourceHref, CreatedResourceLink, CreatedResourceLinkBase, InferHashFromResourceLinkHref, ResourceAnchorLinkFn, ResourceLinkHref } from "./create-resource-links.mjs";
|
|
4
4
|
import { CreateResourceLayoutFn, CreateResourceLayoutMakeComposableOptions, defineResourceLayout } from "./define-layout.mjs";
|