Source Toolbar
Source Toolbar
Cette page est générée automatiquement à partir du dépôt local au moment de la génération de la documentation.
Fichiers inclus
packages/common/src/lib/widgets/toolbar/toolbar.declaration.tspackages/common/src/lib/widgets/toolbar/toolbar.config.tspackages/common/src/lib/widgets/toolbar/toolbar.i18n.tspackages/common/src/lib/widgets/toolbar/Toolbar.sveltepackages/common/src/lib/widgets/toolbar/ToolbarItem.svelte
packages/common/src/lib/widgets/toolbar/toolbar.declaration.ts
import { widgetFactorySvelte, type WidgetProps } from '$lib/api/managers/widget';import { type ToolbarConfig, toolbarConfigSchema } from './toolbar.config';import type { WidgetDeclaration } from '$lib/api/managers/widget/widget-declaration';
export const declaration = { factory: () => import('./Toolbar.svelte').then((Toolbar) => widgetFactorySvelte(Toolbar)), schema: () => toolbarConfigSchema,} satisfies WidgetDeclaration;
export type ToolbarProps = WidgetProps<ToolbarConfig>;packages/common/src/lib/widgets/toolbar/toolbar.config.ts
import { defineWidgetConfig } from '$lib/api/managers/configuration/models/widget/widget-configuration.schema';import { DEFAULT_TOOLBAR_ID, inToolbarSchemaFrom,} from '$lib/api/managers/configuration/models/widget/widget-in-toolbar.schema';import { mapIconSchema } from '$lib/components/icon/map-icon';import { z } from 'zod';import { styleRecordSchema } from '$lib/api/utils/style/style.schema';import { i18nSchemaFrom } from '$lib/api/managers/i18n';import { toolbarI18n } from '$lib/widgets/toolbar/toolbar.i18n';
export const sideEnumSchema = z.enum([ 'top', // 'top-start', // 'top-end', 'bottom', // 'bottom-start', // 'bottom-end', 'left', // 'left-start', // 'left-end', 'right', // 'right-start', // 'right-end',]);export const toolbarConfigSchema = defineWidgetConfig({ active: true, inToolbar: inToolbarSchemaFrom(false), i18n: i18nSchemaFrom(toolbarI18n), config: z .object({ widgetsIds: z.array(z.string()).optional(), iconStyle: mapIconSchema.optional(), display: z.enum(['full', 'light']).default('light'), orientation: z.enum(['right', 'left', 'up', 'down']).default('right'), tooltipSide: sideEnumSchema.default('bottom'), toolbarId: z.string().default(DEFAULT_TOOLBAR_ID), style: styleRecordSchema.optional(), }) .prefault({}),});
export type ToolbarConfig = z.infer<typeof toolbarConfigSchema>;export type ToolbarDisplay = ToolbarConfig['config']['display'];export type ToolbarI18n = ToolbarConfig['i18n'];packages/common/src/lib/widgets/toolbar/toolbar.i18n.ts
import type { I18nRegistry } from '$lib/api/managers/i18n';
export const toolbarI18n = {} satisfies I18nRegistry;packages/common/src/lib/widgets/toolbar/Toolbar.svelte
<script lang="ts"> import type { WidgetConfig } from '$lib/api/managers/configuration'; import { getConfigurationManager } from '$lib/api/managers/configuration/configuration.manager.svelte'; import { getWidgetManager } from '$lib/api/managers/widget/widget.manager.svelte'; import type { ContainerConfig, ContainerWidgetConfig } from '$lib/components/containers'; import { ToolbarTabs } from '$lib/components/containers/toolbar-tabs'; import type { ToolbarTabsConfig } from '$lib/components/containers/toolbar-tabs/toolbar-tabs.schema'; import { cn } from '$lib/components/shadcn/utils'; import ToolbarItem from './ToolbarItem.svelte'; import { recordToCssStyle } from '$lib/api/utils/style/style.utils'; import type { ToolbarProps } from './toolbar.declaration';
const { fullConfig }: ToolbarProps = $props();
const config = $derived(fullConfig.config);
const configurationManager = getConfigurationManager(); const widgetManager = getWidgetManager();
const inToolbarWidgets = $derived.by(() => { const inToolbar = configurationManager.widgetsConfiguration!.filter( (w) => w.inToolbar && w.inToolbar.toolbarId === config.toolbarId, ) as WidgetConfig[]; const toolbarTabs = configurationManager.viewerConfiguration!.containers.filter((c) => isToolbarTabConfig(c, config.toolbarId), );
return [...inToolbar, ...toolbarTabs].sort((a, b) => { const aOrder = getOrder(a); const bOrder = getOrder(b); return aOrder - bOrder; }); });
function getOrder(item: WidgetConfig | ToolbarTabsConfig): number { if (isToolbarTabs(item)) { return item.order ?? 0; } else { return item.inToolbar?.order ?? 0; } }
function getKey(item: WidgetConfig | ToolbarTabsConfig): string { if (isToolbarTabs(item)) { return `toolbar-tab-${item.id}`; } else { return item.widgetId; } }
function isToolbarTabs(item: WidgetConfig | ToolbarTabsConfig): item is ToolbarTabsConfig { return 'type' in item && item.type === 'toolbar-tabs'; }
function isToolbarTabConfig( container: ContainerConfig | ContainerWidgetConfig | string, toolbarId: string, ): container is ToolbarTabsConfig { return ( !!container && typeof container === 'object' && 'type' in container && container.type === 'toolbar-tabs' && container.toolbarId === toolbarId ); }
async function toggleWidget(widgetId: string) { const reference = widgetManager.getReference(widgetId); reference.toggle({ openContainer: true }); }</script>
<div class={cn( 'toolbar-container gv-flex gv-rounded-full gv-overflow-hidden gv-text-primary gv-border-2 gv-border-background', { 'gv-flex-row-reverse gv-divide-x gv-divide-x-reverse': config.orientation === 'left', 'gv-flex-row gv-divide-x': config.orientation === 'right', 'gv-flex-col-reverse gv-divide-y gv-divide-y-reverse': config.orientation === 'up', 'gv-flex-col gv-divide-y': config.orientation === 'down', }, )} style={recordToCssStyle(fullConfig.config.style)}> {#each inToolbarWidgets as widget (getKey(widget))} {#if isToolbarTabs(widget)} <ToolbarTabs config={widget} class="gv-shadow-4md" /> {:else} <ToolbarItem widgetConfig={widget} i18nConfig={fullConfig.i18n} display={config.display} tooltipSide={config.tooltipSide} onclick={() => toggleWidget(widget.widgetId)} style={recordToCssStyle(widget.inToolbar?.style)} /> {/if} {/each}</div>
<style> .toolbar-container { box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25); }</style>packages/common/src/lib/widgets/toolbar/ToolbarItem.svelte
<script lang="ts"> import type { WidgetConfig } from '$lib/api/managers/configuration'; import { isActiveIcon } from '$lib/api/managers/configuration/models/widget/widget-in-toolbar.schema'; import { getI18n } from '$lib/api/managers/i18n'; import { getWidgetManager } from '$lib/api/managers/widget'; import { ApiSimpleTooltip, type TooltipSide } from '$lib/components/api-simple-tooltip'; import WidgetContainer from '$lib/components/containers/WidgetContainer.svelte'; import Icon from '$lib/components/icon/Icon.svelte'; import { type MapIconSize, type MapIconVariant, mapIconButtonVariants, mapIconVariants, } from '$lib/components/icon/map-icon'; import { cn } from '$lib/components/shadcn/utils'; import type { ToolbarDisplay, ToolbarI18n } from './toolbar.config'; import type { HTMLAttributes } from 'svelte/elements';
interface Props extends HTMLAttributes<HTMLButtonElement> { widgetConfig: WidgetConfig; i18nConfig: ToolbarI18n; display: ToolbarDisplay; variant?: MapIconVariant; size?: MapIconSize; tooltipSide: TooltipSide; onclick?: (e: MouseEvent) => void; class?: string; }
let { widgetConfig, i18nConfig, display, variant = 'default', size = 'default', tooltipSide, onclick, class: className, ...restProps }: Props = $props();
const widgetManager = getWidgetManager(); const i18n = getI18n(i18nConfig); const toolbarConfig = $derived(widgetConfig.inToolbar!); const title = $derived( toolbarConfig.type === 'button' ? i18n.translate(toolbarConfig.label ?? widgetConfig.title) : undefined, ); // FIXME: remove this when WOM features are fully released (xd) const tooltipText = $derived( toolbarConfig.type === 'button' && toolbarConfig.disabled ? i18n('common.incoming-tool', { tool: title }) : title, ); const icon = $derived(toolbarConfig.type === 'button' ? (toolbarConfig.icon ?? widgetConfig.icon) : undefined); const reference = widgetManager.getReference(widgetConfig.widgetId);</script>
{#if toolbarConfig.type === 'button'} <ApiSimpleTooltip text={tooltipText} side={tooltipSide} openDelay={0}> <div class={cn('gv-bg-background gv-contents', mapIconButtonVariants.variants.size[size], className)}> <button {onclick} disabled={toolbarConfig.disabled} data-test-id="ToolbarItem-{widgetConfig.widgetId}" class={cn(mapIconButtonVariants({ variant, size }))} data-state={reference.active ? 'active' : ''} {...restProps} > {#if display === 'full'} <span class="gv-text-[11px]">{title}</span> {/if} {#if isActiveIcon(icon)} <Icon icon={reference.active ? icon.active : icon.inactive} class={mapIconVariants()}></Icon> {:else} <Icon {icon} class={mapIconVariants({ size })}></Icon> {/if} </button> </div> </ApiSimpleTooltip>{:else if toolbarConfig.type === 'integrated'} {#if reference.active} <WidgetContainer {reference} class={className} /> {/if}{/if}