diff --git a/src/content/local-docs/libs/dashkit/README-de.md b/src/content/local-docs/libs/dashkit/README-de.md index fc9d5c5f1548..7547184a7c71 100644 --- a/src/content/local-docs/libs/dashkit/README-de.md +++ b/src/content/local-docs/libs/dashkit/README-de.md @@ -2,7 +2,7 @@ # DashKit -Eine Bibliothek zum Rendern von Dashboard-Grids. +Eine Bibliothek zum Rendern von Dashboard-Gittern. ## Installation @@ -12,7 +12,7 @@ npm i @gravity-ui/dashkit @gravity-ui/uikit ## Beschreibung -Die Bibliothek wird verwendet, um Widgets in einem Grid anzuordnen, ihre Größe zu ändern, neue hinzuzufügen und sie zu löschen. +Die Bibliothek wird verwendet, um Widgets in einem Raster anzuordnen, ihre Größe zu ändern, neue hinzuzufügen und sie zu löschen. Das Widget ist eine React-Komponente. Zum Beispiel Text, Grafiken und Bilder. Neue Widgets werden über ein Plugin-System hinzugefügt. @@ -25,12 +25,12 @@ Plugins sind erforderlich, um benutzerdefinierte Widgets zu erstellen. ```ts type ItemManipulationCallback = (eventData: { - layout: Layout[]; - oldItem: Layout; - newItem: Layout; - placeholder: Layout; - e: MouseEvent; - element: HTMLElement; + layout: Layout[]; + oldItem: Layout; + newItem: Layout; + placeholder: Layout; + e: MouseEvent; + element: HTMLElement; }) => void; interface DashKitProps { @@ -68,21 +68,21 @@ interface DashKitProps { } ``` -- **config**: [сonfig](#Config). +- **config**: [Konfiguration](#Config). - **editMode**: Ob der Bearbeitungsmodus aktiviert ist. - **onItemEdit**: Wird aufgerufen, wenn Sie auf ein Widget klicken, um es zu bearbeiten. -- **onChange**: Wird aufgerufen, wenn sich die Konfiguration oder [itemsStateAndParams](#itemsStateAndParams) ändern. -- **onDrop**: Wird aufgerufen, wenn ein Element aus der ActionPanel über (#DashKitDnDWrapper) fallen gelassen wird. +- **onChange**: Wird aufgerufen, wenn die Konfiguration oder [itemsStateAndParams](#itemsStateAndParams) geändert werden. +- **onDrop**: Wird aufgerufen, wenn ein Element über (#DashKitDnDWrapper) von der ActionPanel fallen gelassen wird. - **onItemMountChange**: Wird aufgerufen, wenn sich der Mount-Status eines Elements ändert. - **onItemRender**: Wird aufgerufen, wenn das Rendern eines Elements abgeschlossen ist. - **defaultGlobalParams**, **globalParams**: [Parameter](#Params), die alle Widgets beeinflussen. In DataLens sind `defaultGlobalParams` globale Parameter, die in den Dashboard-Einstellungen festgelegt sind. `globalParams` sind globale Parameter, die in der URL gesetzt werden können. - **itemsStateAndParams**: [itemsStateAndParams](#itemsStateAndParams). - **settings**: DashKit-Einstellungen. - **context**: Objekt, das an alle Widgets weitergegeben wird. -- **overlayControls**: Objekt, das die Widget-Steuerelemente während der Bearbeitung überschreibt. Wenn nicht übergeben, werden grundlegende Steuerelemente angezeigt. Wenn `null` übergeben wird, werden nur die Schließen-Schaltfläche oder ein benutzerdefiniertes Menü angezeigt. +- **overlayControls**: Objekt, das die Widget-Steuerelemente während der Bearbeitung überschreibt. Wenn nicht übergeben, werden grundlegende Steuerelemente angezeigt. Wenn `null` übergeben wird, werden nur der Schließen-Button oder ein benutzerdefiniertes Menü angezeigt. - **overlayMenuItems**: Benutzerdefinierte Dropdown-Menüelemente. -- **noOverlay**: Wenn `true`, werden Overlays und Steuerelemente während der Bearbeitung nicht angezeigt. -- **focusable**: Wenn `true`, sind Grid-Elemente fokussierbar. +- **noOverlay**: Wenn `true`, werden Overlay und Steuerelemente während der Bearbeitung nicht angezeigt. +- **focusable**: Wenn `true`, sind die Rasterelemente fokussierbar. - **onItemFocus**: Wird aufgerufen, wenn `focusable` true ist und ein Element fokussiert wird. - **onItemBlur**: Wird aufgerufen, wenn `focusable` true ist und ein Element den Fokus verliert. - **draggableHandleClassName**: CSS-Klassenname des Elements, das das Widget ziehbar macht. @@ -92,14 +92,14 @@ interface DashKitProps { - **onResizeStart**: Wird von ReactGridLayout aufgerufen, wenn die Größenänderung eines Elements beginnt. - **onResize**: Wird von ReactGridLayout während der Größenänderung eines Elements aufgerufen. - **onResizeStop**: Wird von ReactGridLayout aufgerufen, wenn die Größenänderung eines Elements beendet wird. -- **getPreparedCopyItemOptions**: Wird aufgerufen, um ein kopiertes Element in ein serialisierbares Objekt umzuwandeln, bevor es im LocalStorage gespeichert wird. Dies sollte anstelle des veralteten Props `context.getPreparedCopyItemOptions` verwendet werden. +- **getPreparedCopyItemOptions**: Wird aufgerufen, um ein kopiertes Element in ein serialisierbares Objekt zu konvertieren, bevor es im LocalStorage gespeichert wird. Es sollte anstelle des veralteten `context.getPreparedCopyItemOptions`-Props verwendet werden. - **onCopyFulfill**: Wird aufgerufen, wenn das Kopieren eines Elements abgeschlossen ist. Bei Erfolg wird `error=null` und `data` übergeben, andernfalls `error: Error` ohne `data`. ## Verwendung ### DashKit-Konfiguration -Bevor Sie `DashKit` als React-Komponente verwenden können, muss es konfiguriert werden. +Bevor Sie `DashKit` als React-Komponente verwenden, muss es konfiguriert werden. - Sprache festlegen @@ -152,20 +152,20 @@ Bevor Sie `DashKit` als React-Komponente verwenden können, muss es konfiguriert }); ``` -### Config +### Konfiguration ```ts export interface Config { salt: string; // zum Erstellen einer eindeutigen ID - counter: number; // zum Erstellen einer eindeutigen ID, wird nur erhöht + counter: number; // zum Erstellen einer eindeutigen ID, erhöht sich nur items: ConfigItem[]; // anfängliche Widget-Zustände - layout: ConfigLayout[]; // Widget-Position im Grid https://github.com/react-grid-layout + layout: ConfigLayout[]; // Widget-Position im Raster https://github.com/react-grid-layout aliases: ConfigAliases; // Aliase für Parameter siehe #Params connections: ConfigConnection[]; // Links zwischen Widgets siehe #Params } ``` -Config-Beispiel: +Konfigurationsbeispiel: ```ts import {DashKitProps} from '@gravity-ui/dashkit'; @@ -190,7 +190,7 @@ const config: DashKitProps['config'] = { { id: 'Ea', data: { - text: 'modus _editActive', + text: 'Modus _editActive', _editActive: true, }, type: 'text', @@ -287,7 +287,7 @@ const newConfig = DashKit.setItem({ }, config: config, options: { - // Optional. Neue Layoutwerte für vorhandene Elemente, wenn ein neues Element aus der Aktionsleiste gezogen wird + // Optional. Neue Layoutwerte für vorhandene Elemente, wenn ein neues Element aus der ActionPanel gezogen wird updateLayout: newLayout, }, }); @@ -348,7 +348,7 @@ Es hat ein `__meta__`-Feld zum Speichern von Warteschlangen- und Metainformation interface StateAndParamsMeta = { __meta__: { queue: {id: string}[]; // Warteschlange - version: number; // aktuelle Version itemsStateAndParams + version: number; // Aktuelle Version von itemsStateAndParams }; } ``` @@ -368,19 +368,93 @@ interface ItemsStateAndParamsBase { type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase; ``` +### Experimentelle DashKit-Ereignisse + +> Experimentell: Diese API kann sich in kleineren Releases ändern. + +`DashKit` stellt eine experimentelle Instanz-Ereignis-API bereit. Verwenden Sie eine Komponentenreferenz und abonnieren Sie mit `dashkitRef.current?.on(eventName, handler)`. Die Methode gibt eine Funktion zum Abbestellen zurück. + +Das erste unterstützte Ereignis ist `change`. Es wird ausgelöst, wenn sich das Layout ändert, bevor `onChange` aufgerufen wird. Der Handler kann die vollständigen nächsten und vorherigen Layouts lesen, Layout-Patches lesen oder `preventDefault()` aufrufen, um den Standardaufruf von `onChange` zu stoppen. + +```tsx +import React from 'react'; +import {DashKit} from '@gravity-ui/dashkit'; +import type {DashKitChangeEvent} from '@gravity-ui/dashkit'; + +function Dashboard() { + const dashkitRef = React.useRef(null); + + React.useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event: DashKitChangeEvent) => { + console.log(event.patches); + + if (event.patches.length > 0) { + event.preventDefault(); + } + }); + + return () => unsubscribe?.(); + }, []); + + return ; +} +``` + +```ts +type DashKitLayoutPatch = Pick & + Partial>; + +type DashKitChangeEvent = { + patches: DashKitLayoutPatch[]; + layout: ConfigLayout[]; + previousLayout: ConfigLayout[]; + preventDefault: () => void; + readonly defaultPrevented: boolean; +}; +``` + +#### Ereignisgesteuerte Layout-Updates + +Wenn Sie `preventDefault()` im `change`-Ereignis-Handler verwenden, können Sie Layout-Updates jetzt behandeln, ohne die `config`-Prop neu zu initialisieren. DashKit verwaltet eine interne Basislinie und berechnet Patches inkrementell: + +```tsx +function Dashboard() { + const [config, setConfig] = useState(initialConfig); + const dashkitRef = useRef(null); + + useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event) => { + event.preventDefault(); // onChange nicht aufrufen + + // Nur die inkrementellen Patches an Ihr Backend senden + sendPatches(event.patches); + + // Kein Aufruf von setConfig({ ...config, layout: event.layout }) erforderlich + // DashKit verwaltet den visuellen Zustand intern + }); + + return unsubscribe; + }, []); + + return {}} />; +} +``` + +**Wichtig:** Wenn Sie `config.layout` später über Props aktualisieren (z. B. durch Synchronisierung vom Server), setzt DashKit seine interne Basislinie zurück, um mit der neuen Prop übereinzustimmen. Dies gewährleistet die Kompatibilität mit ereignisgesteuerten und gesteuerten Workflows. + ### Menü -Sie können ein benutzerdefiniertes Overlay-Menü für DashKit-Widgets im Bearbeitungsmodus angeben +Sie können ein benutzerdefiniertes DashKit-Widget-Overlay-Menü im Bearbeitungsmodus festlegen. ```ts type MenuItem = { - id: string; // eindeutige ID - title?: string; // Zeichenfolgentitel - icon?: ReactNode; // Knoten des Symbols - iconSize?: number | string; // Symbolgröße in px als Zahl oder als Zeichenfolge mit Einheiten - handler?: (item: ConfigItem) => void; // benutzerdefinierter Aktionshandler für Elemente - visible?: (item: ConfigItem) => boolean; // optionaler Sichtbarkeits-Handler zum Filtern von Menüelementen - className?: string; // benutzerdefinierte Klasseneigenschaft + id: string; // Eindeutige ID + title?: string; // String-Titel + icon?: ReactNode; // Icon-Knoten + iconSize?: number | string; // Icon-Größe in px als Zahl oder als String mit Einheiten + handler?: (item: ConfigItem) => void; // Benutzerdefinierter Handler für die Elementaktion + visible?: (item: ConfigItem) => boolean; // Optionaler Sichtbarkeits-Handler zum Filtern von Menüelementen + className?: string; // Benutzerdefinierte Klassen-Eigenschaft }; // Array von Menüelementen in den Einstellungen verwenden @@ -408,35 +482,38 @@ interface DashKitDnDWrapperProps { dragImageSrc?: string; onDragStart?: (dragProps: ItemDragProps) => void; onDragEnd?: () => void; - onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) => void | boolean; + onDropDragOver?: ( + draggedItem: DraggedOverItem, + sharedItem: DraggedOverItem | null, + ) => void | boolean; } ``` -- **dragImageSrc**: Vorschau des Ziehbilds, standardmäßig wird ein transparentes 1px PNG als Base64 verwendet -- **onDragStart**: Rückruf, der aufgerufen wird, wenn ein Element aus der Aktionsleiste gezogen wird -- **onDragEnd**: Rückruf, der aufgerufen wird, wenn ein Element abgelegt oder der Ziehvorgang abgebrochen wird +- **dragImageSrc**: Vorschau des Ziehbilds, standardmäßig wird ein transparenter 1px PNG Base64 verwendet. +- **onDragStart**: Callback, der aufgerufen wird, wenn ein Element aus der Aktionsleiste gezogen wird. +- **onDragEnd**: Callback, der aufgerufen wird, wenn ein Element fallen gelassen oder der Ziehvorgang abgebrochen wird. ```ts type ItemDragProps = { - type: string; // Plugin-Typ - layout?: { // Optional. Layout-Elementgröße für Vorschau und Initialisierung - w?: number; - h?: number; - }; - extra?: any; // Benutzerdefinierter Kontext + type: string; // Plugin-Typ + layout?: { + // Optional. Layout-Elementgröße für Vorschau und Initialisierung + w?: number; + h?: number; + }; + extra?: any; // Benutzerdefinierter Kontext }; ``` ```ts type ItemDropProps = { - commit: () => void; // Callback, der nach Abschluss aller Konfigurationsoperationen aufgerufen werden sollte - dragProps: ItemDragProps; // Item-Drag-Props - itemLayout: ConfigLayout; // Berechnete Layout-Dimensionen des Elements - newLayout: ConfigLayout[]; // Neues Layout nach dem Ablegen des Elements + commit: () => void; // Callback sollte nach allen Konfigurationsoperationen aufgerufen werden + dragProps: ItemDragProps; // Item-Drag-Props + itemLayout: ConfigLayout; // Berechnete Layout-Dimensionen des Elements + newLayout: ConfigLayout[]; // Neues Layout nach dem Ablegen des Elements }; ``` - #### Beispiel: ```jsx @@ -467,23 +544,23 @@ const onDrop = (dropProps: ItemDropProps) => { | Name | Beschreibung | | :--------------------------------------------- | :-------------------- | -| Action panel Variablen | | +| Aktionsleisten-Variablen | | | `--dashkit-action-panel-color` | Hintergrundfarbe | -| `--dashkit-action-panel-border-color` | Rahmenfarbe | -| `--dashkit-action-panel-border-radius` | Rahmenradius | -| Action panel Element Variablen | | +| `--dashkit-action-panel-border-color` | Randfarbe | +| `--dashkit-action-panel-border-radius` | Randradius | +| Aktionsleisten-Element-Variablen | | | `--dashkit-action-panel-item-color` | Hintergrundfarbe | | `--dashkit-action-panel-item-text-color` | Textfarbe | -| `--dashkit-action-panel-item-color-hover` | Hintergrundfarbe (Hover) | -| `--dashkit-action-panel-item-text-color-hover` | Textfarbe (Hover) | -| Overlay Variablen | | -| `--dashkit-overlay-border-color` | Rahmenfarbe | +| `--dashkit-action-panel-item-color-hover` | Hintergrundfarbe bei Hover | +| `--dashkit-action-panel-item-text-color-hover` | Textfarbe bei Hover | +| Overlay-Variablen | | +| `--dashkit-overlay-border-color` | Randfarbe | | `--dashkit-overlay-color` | Hintergrundfarbe | | `--dashkit-overlay-opacity` | Deckkraft | -| Grid Element Variablen | | +| Gitter-Element-Variablen | | | `--dashkit-grid-item-edit-opacity` | Deckkraft | -| `--dashkit-grid-item-border-radius` | Rahmenradius | -| Platzhalter Variablen | | +| `--dashkit-grid-item-border-radius` | Randradius | +| Platzhalter-Variablen | | | `--dashkit-placeholder-color` | Hintergrundfarbe | | `--dashkit-placeholder-opacity` | Deckkraft | @@ -527,8 +604,7 @@ const CustomThemeWrapper = (props: { - Storybook bauen `npm run start` Standardmäßig läuft Storybook unter `http://localhost:7120/`. -Neue Änderungen im Projekt werden nicht immer übernommen, wenn Storybook läuft. Daher ist es besser, ein Projekt manuell neu zu bauen und Storybook neu zu starten. - +Neue Änderungen im Projekt werden nicht immer übernommen, wenn Storybook läuft. Daher ist es besser, das Projekt manuell neu zu bauen und Storybook neu zu starten. ### Beispiel für eine Nginx-Konfiguration für die Entwicklung auf einem Entwicklungsrechner diff --git a/src/content/local-docs/libs/dashkit/README-es.md b/src/content/local-docs/libs/dashkit/README-es.md index a6485404eb1b..138cc1e68c15 100644 --- a/src/content/local-docs/libs/dashkit/README-es.md +++ b/src/content/local-docs/libs/dashkit/README-es.md @@ -2,7 +2,7 @@ # DashKit -Una biblioteca para renderizar cuadrículas de paneles. +Una librería para renderizar cuadrículas de dashboards. ## Instalación @@ -12,10 +12,10 @@ npm i @gravity-ui/dashkit @gravity-ui/uikit ## Descripción -La biblioteca se utiliza para alinear widgets en una cuadrícula, cambiar su tamaño, agregar nuevos y eliminarlos. -El widget es un componente de React. Por ejemplo, texto, gráficos e imágenes. +La librería se utiliza para alinear widgets en una cuadrícula, redimensionarlos, añadir nuevos y eliminarlos. +Un widget es un componente de React. Por ejemplo, texto, gráficos e imágenes. -Los nuevos widgets se agregan a través de un sistema de plugins. +Los nuevos widgets se añaden a través de un sistema de plugins. ### Plugins @@ -25,12 +25,12 @@ Los plugins son necesarios para crear widgets personalizados. ```ts type ItemManipulationCallback = (eventData: { - layout: Layout[]; - oldItem: Layout; - newItem: Layout; - placeholder: Layout; - e: MouseEvent; - element: HTMLElement; + layout: Layout[]; + oldItem: Layout; + newItem: Layout; + placeholder: Layout; + e: MouseEvent; + element: HTMLElement; }) => void; interface DashKitProps { @@ -69,31 +69,31 @@ interface DashKitProps { ``` - **config**: [Config](#Config). -- **editMode**: Si el modo de edición está habilitado. -- **onItemEdit**: Se llama cuando haces clic para editar un widget. -- **onChange**: Se llama cuando cambian la configuración o [itemsStateAndParams](#itemsStateAndParams). -- **onDrop**: Se llama cuando un elemento se suelta desde ActionPanel usando (#DashKitDnDWrapper) -- **onItemMountChange**: Se llama cuando cambia el estado de montaje del elemento. -- **onItemRender**: Se llama cuando se completa el renderizado del elemento. -- **defaultGlobalParams**, **globalParams**: [Parámetros](#Params) que afectan a todos los widgets. En DataLens, `defaultGlobalParams` son parámetros globales establecidos en la configuración del panel. `globalParams` son parámetros globales que se pueden establecer en la URL. +- **editMode**: Indica si el modo de edición está habilitado. +- **onItemEdit**: Se llama al hacer clic para editar un widget. +- **onChange**: Se llama cuando se modifican la configuración o los [itemsStateAndParams](#itemsStateAndParams). +- **onDrop**: Se llama cuando un elemento se suelta desde ActionPanel usando (#DashKitDnDWrapper). +- **onItemMountChange**: Se llama cuando cambia el estado de montaje de un elemento. +- **onItemRender**: Se llama cuando finaliza el renderizado de un elemento. +- **defaultGlobalParams**, **globalParams**: [Parámetros](#Params) que afectan a todos los widgets. En DataLens, `defaultGlobalParams` son los parámetros globales establecidos en la configuración del dashboard. `globalParams` son parámetros globales que se pueden establecer en la URL. - **itemsStateAndParams**: [itemsStateAndParams](#itemsStateAndParams). - **settings**: Configuración de DashKit. - **context**: Objeto que se pasará a todos los widgets. -- **overlayControls**: Objeto que anula los controles del widget durante la edición. Si no se transmite, se mostrarán los controles básicos. Si se pasa `null`, solo se mostrará el botón de cierre o un menú personalizado. +- **overlayControls**: Objeto que anula los controles del widget durante la edición. Si no se proporciona, se mostrarán los controles básicos. Si se pasa `null`, solo se mostrará el botón de cierre o un menú personalizado. - **overlayMenuItems**: Elementos del menú desplegable personalizados. -- **noOverlay**: Si es `true`, la superposición y los controles no se mostrarán durante la edición. +- **noOverlay**: Si es `true`, la superposición y los controles no se muestran durante la edición. - **focusable**: Si es `true`, los elementos de la cuadrícula serán enfocables. -- **onItemFocus**: Se llama cuando `focusable` es true y el elemento tiene el foco. -- **onItemBlur**: Se llama cuando `focusable` es true y el elemento pierde el foco. +- **onItemFocus**: Se llama cuando `focusable` es `true` y un elemento recibe el foco. +- **onItemBlur**: Se llama cuando `focusable` es `true` y un elemento pierde el foco. - **draggableHandleClassName**: Nombre de la clase CSS del elemento que hace que el widget sea arrastrable. -- **onDragStart**: ReactGridLayout se llama cuando comienza a arrastrar un elemento. -- **onDrag**: ReactGridLayout se llama mientras se arrastra un elemento. -- **onDragStop**: ReactGridLayout se llama cuando se detiene el arrastre de un elemento. -- **onResizeStart**: ReactGridLayout se llama cuando comienza a redimensionar un elemento. -- **onResize**: ReactGridLayout se llama mientras se redimensiona un elemento. -- **onResizeStop**: ReactGridLayout se llama cuando se detiene el redimensionamiento de un elemento. -- **getPreparedCopyItemOptions**: Se llama para convertir un elemento copiado en un objeto serializable antes de guardarlo en el almacenamiento local. Debe usarse en lugar de la prop obsoleta `context.getPreparedCopyItemOptions`. -- **onCopyFulfill**: Se llama cuando la copia del elemento finaliza con `error=null` y `data` definido en caso de operación exitosa, y con `error: Error` sin `data` en caso contrario. +- **onDragStart**: Se llama desde ReactGridLayout cuando se inicia el arrastre de un elemento. +- **onDrag**: Se llama desde ReactGridLayout mientras se arrastra un elemento. +- **onDragStop**: Se llama desde ReactGridLayout cuando se detiene el arrastre de un elemento. +- **onResizeStart**: Se llama desde ReactGridLayout cuando se inicia el redimensionamiento de un elemento. +- **onResize**: Se llama desde ReactGridLayout mientras se redimensiona un elemento. +- **onResizeStop**: Se llama desde ReactGridLayout cuando se detiene el redimensionamiento de un elemento. +- **getPreparedCopyItemOptions**: Se llama para convertir un elemento copiado en un objeto serializable antes de guardarlo en el localStorage. Debe usarse en lugar de la prop obsoleta `context.getPreparedCopyItemOptions`. +- **onCopyFulfill**: Se llama cuando la copia de un elemento finaliza con `error=null` y `data` definido en caso de éxito, y con `error: Error` sin `data` en caso contrario. ## Uso @@ -101,7 +101,7 @@ interface DashKitProps { Antes de usar `DashKit` como un componente de React, debe configurarse. -- Establecer idioma +- Establecer el idioma ```js import {configure, Lang} from '@gravity-ui/uikit'; @@ -111,7 +111,7 @@ Antes de usar `DashKit` como un componente de React, debe configurarse. - DashKit.setSettings - Se utiliza para la configuración global de DashKit (como márgenes entre widgets, tamaños predeterminados de widgets y menú de superposición de widgets). + Se utiliza para la configuración global de DashKit (como márgenes entre widgets, tamaños de widget predeterminados y menú de superposición de widgets). ```js import {DashKit} from '@gravity-ui/dashkit'; @@ -147,7 +147,7 @@ Antes de usar `DashKit` como un componente de React, debe configurarse. h: 8, }, renderer: function CustomPlugin() { - return
Custom widget with custom controls
; + return
Widget personalizado con controles personalizados
; }, }); ``` @@ -277,7 +277,7 @@ const newConfig = DashKit.setItem({ }, namespace: 'default', type: 'text', - // Opcional. Si se necesita insertar un nuevo elemento en el layout actual con dimensiones predefinidas + // Opcional. Si se necesita insertar un nuevo elemento en el diseño actual con dimensiones predefinidas layout: { // El elemento actual se inserta antes de 'Ea' h: 6, w: 12, @@ -287,7 +287,7 @@ const newConfig = DashKit.setItem({ }, config: config, options: { - // Opcional. Nuevos valores de layout para elementos existentes cuando se suelta un nuevo elemento desde ActionPanel + // Opcional. Nuevos valores de diseño para elementos existentes cuando se suelta un nuevo elemento desde ActionPanel updateLayout: newLayout, }, }); @@ -353,7 +353,7 @@ interface StateAndParamsMeta = { } ``` -Y también estados y parámetros de widgets: +Y también estados y parámetros de los widgets: ```ts interface ItemsStateAndParamsBase { @@ -368,9 +368,83 @@ interface ItemsStateAndParamsBase { type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase; ``` +### Eventos experimentales de DashKit + +> Experimental: esta API puede cambiar en versiones menores. + +`DashKit` expone una API de eventos de instancia experimental. Utiliza una referencia de componente y suscríbete con `dashkitRef.current?.on(eventName, handler)`. El método devuelve una función de cancelación de suscripción. + +El primer evento admitido es `change`. Se emite cuando cambia el diseño, antes de que se llame a `onChange`. El manejador puede leer los diseños completos anterior y siguiente, leer los parches del diseño o llamar a `preventDefault()` para detener la llamada predeterminada a `onChange`. + +```tsx +import React from 'react'; +import {DashKit} from '@gravity-ui/dashkit'; +import type {DashKitChangeEvent} from '@gravity-ui/dashkit'; + +function Dashboard() { + const dashkitRef = React.useRef(null); + + React.useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event: DashKitChangeEvent) => { + console.log(event.patches); + + if (event.patches.length > 0) { + event.preventDefault(); + } + }); + + return () => unsubscribe?.(); + }, []); + + return ; +} +``` + +```ts +type DashKitLayoutPatch = Pick & + Partial>; + +type DashKitChangeEvent = { + patches: DashKitLayoutPatch[]; + layout: ConfigLayout[]; + previousLayout: ConfigLayout[]; + preventDefault: () => void; + readonly defaultPrevented: boolean; +}; +``` + +#### Actualizaciones de diseño basadas en eventos + +Si utilizas `preventDefault()` en el manejador del evento `change`, ahora puedes gestionar las actualizaciones de diseño sin volver a inicializar la prop `config`. DashKit mantiene una línea base interna y calcula los parches de forma incremental: + +```tsx +function Dashboard() { + const [config, setConfig] = useState(initialConfig); + const dashkitRef = useRef(null); + + useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event) => { + event.preventDefault(); // No llamar a onChange + + // Envía solo los parches incrementales a tu backend + sendPatches(event.patches); + + // No es necesario llamar a setConfig({ ...config, layout: event.layout }) + // DashKit mantiene el estado visual internamente + }); + + return unsubscribe; + }, []); + + return {}} />; +} +``` + +**Importante:** Si más tarde actualizas `config.layout` desde las props (por ejemplo, desde una sincronización del servidor), DashKit restablecerá su línea base interna para que coincida con la nueva prop. Esto garantiza la compatibilidad tanto con flujos de trabajo basados en eventos como controlados. + ### Menú -Puedes especificar un menú superpuesto personalizado para los widgets de DashKit en modo de edición. +Puedes especificar un menú superpuesto de widgets DashKit personalizado en modo de edición ```ts type MenuItem = { @@ -378,12 +452,12 @@ type MenuItem = { title?: string; // título de texto icon?: ReactNode; // nodo de icono iconSize?: number | string; // tamaño del icono en px como número o como cadena con unidades - handler?: (item: ConfigItem) => void; // manejador de acción personalizado del elemento + handler?: (item: ConfigItem) => void; // manejador de acción de elemento personalizado visible?: (item: ConfigItem) => boolean; // manejador de visibilidad opcional para filtrar elementos del menú className?: string; // propiedad de clase personalizada }; -// usar un array de elementos de menú en la configuración +// usa un array de elementos de menú en la configuración | null} /> [obsoleto] @@ -391,7 +465,7 @@ type MenuItem = { DashKit.setSettings({menu: [] as Array}); ``` -### Elementos arrastrables desde ActionPanel +### Arrastrar y soltar elementos desde ActionPanel #### DashKitDnDWrapper @@ -408,35 +482,38 @@ interface DashKitDnDWrapperProps { dragImageSrc?: string; onDragStart?: (dragProps: ItemDragProps) => void; onDragEnd?: () => void; - onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) => void | boolean; + onDropDragOver?: ( + draggedItem: DraggedOverItem, + sharedItem: DraggedOverItem | null, + ) => void | boolean; } ``` -- **dragImageSrc**: Vista previa de la imagen de arrastre, por defecto se utiliza un png transparente de 1px en base64. -- **onDragStart**: Callback que se llama cuando un elemento se arrastra desde ActionPanel. -- **onDragEnd**: Callback que se llama cuando se suelta el elemento o se cancela el arrastre. +- **dragImageSrc**: Vista previa de la imagen de arrastre, por defecto se utiliza un png transparente de 1px en base64 +- **onDragStart**: Callback que se llama cuando un elemento se arrastra desde ActionPanel +- **onDragEnd**: Callback que se llama cuando se suelta el elemento o se cancela el arrastre ```ts type ItemDragProps = { - type: string; // Tipo de plugin - layout?: { // Opcional. Tamaño del elemento de diseño para vista previa e inicialización - w?: number; - h?: number; - }; - extra?: any; // Contexto personalizado del usuario + type: string; // Tipo de plugin + layout?: { + // Opcional. Tamaño del elemento de diseño para vista previa e inicialización + w?: number; + h?: number; + }; + extra?: any; // Contexto de usuario personalizado }; ``` ```ts type ItemDropProps = { - commit: () => void; // La función de callback debe llamarse después de que se realicen todas las operaciones de configuración - dragProps: ItemDragProps; // Propiedades de arrastre del elemento - itemLayout: ConfigLayout; // Dimensiones del diseño del elemento calculadas - newLayout: ConfigLayout[]; // Nuevo diseño después de soltar el elemento + commit: () => void; // Callback que debe llamarse después de que se realicen todas las operaciones de configuración + dragProps: ItemDragProps; // Props de arrastre del elemento + itemLayout: ConfigLayout; // Dimensiones del diseño del elemento calculadas + newLayout: ConfigLayout[]; // Nuevo diseño después de soltar el elemento }; ``` - #### Ejemplo: ```jsx @@ -444,7 +521,7 @@ const overlayMenuItems = [ { id: 'chart', icon: , - title: 'Gráfico', + title: 'Chart', qa: 'chart', dragProps: { // ItemDragProps type: 'custom', // Tipo de plugin registrado @@ -453,7 +530,7 @@ const overlayMenuItems = [ ] const onDrop = (dropProps: ItemDropProps) => { - // ... agregar elemento a tu configuración + // ... agrega el elemento a tu configuración dropProps.commit(); } @@ -463,7 +540,7 @@ const onDrop = (dropProps: ItemDropProps) => { ``` -### API de CSS +### API CSS | Nombre | Descripción | | :--------------------------------------------- | :-------------------- | @@ -471,20 +548,20 @@ const onDrop = (dropProps: ItemDropProps) => { | `--dashkit-action-panel-color` | Color de fondo | | `--dashkit-action-panel-border-color` | Color del borde | | `--dashkit-action-panel-border-radius` | Radio del borde | -| Variables de elementos del panel de acciones | | +| Variables del elemento del panel de acciones | | | `--dashkit-action-panel-item-color` | Color de fondo | | `--dashkit-action-panel-item-text-color` | Color del texto | -| `--dashkit-action-panel-item-color-hover` | Color de fondo al pasar el ratón | +| `--dashkit-action-panel-item-color-hover` | Color de fondo al pasar el ratón | | `--dashkit-action-panel-item-text-color-hover` | Color del texto al pasar el ratón | -| Variables de superposición | | +| Variables de superposición | | | `--dashkit-overlay-border-color` | Color del borde | -| `--dashkit-overlay-color` | Color de fondo | +| `--dashkit-overlay-color` | Color de fondo | | `--dashkit-overlay-opacity` | Opacidad | -| Variables de elementos de la cuadrícula | | +| Variables del elemento de la cuadrícula | | | `--dashkit-grid-item-edit-opacity` | Opacidad | | `--dashkit-grid-item-border-radius` | Radio del borde | -| Variables de marcador de posición | | -| `--dashkit-placeholder-color` | Color de fondo | +| Variables del marcador de posición | | +| `--dashkit-placeholder-color` | Color de fondo | | `--dashkit-placeholder-opacity` | Opacidad | #### Ejemplo de uso @@ -520,15 +597,14 @@ const CustomThemeWrapper = (props: { ## Desarrollo -### Compilar y observar +### Compilación y monitorización - Compilar dependencias `npm ci` - Compilar proyecto `npm run build` - Compilar storybook `npm run start` Por defecto, storybook se ejecuta en `http://localhost:7120/`. -Los nuevos cambios de un proyecto no siempre se detectan cuando storybook está en ejecución, por lo que es mejor recompilar el proyecto manualmente y reiniciar storybook. - +Los cambios nuevos en un proyecto no siempre se detectan cuando storybook está en ejecución, por lo que es mejor recompilar el proyecto manualmente y reiniciar storybook. ### Ejemplo de configuración de nginx para desarrollo en una máquina de desarrollo diff --git a/src/content/local-docs/libs/dashkit/README-fr.md b/src/content/local-docs/libs/dashkit/README-fr.md index 184c4902e628..fe71b956228d 100644 --- a/src/content/local-docs/libs/dashkit/README-fr.md +++ b/src/content/local-docs/libs/dashkit/README-fr.md @@ -25,12 +25,12 @@ Les plugins sont nécessaires pour créer des widgets personnalisés. ```ts type ItemManipulationCallback = (eventData: { - layout: Layout[]; - oldItem: Layout; - newItem: Layout; - placeholder: Layout; - e: MouseEvent; - element: HTMLElement; + layout: Layout[]; + oldItem: Layout; + newItem: Layout; + placeholder: Layout; + e: MouseEvent; + element: HTMLElement; }) => void; interface DashKitProps { @@ -73,33 +73,33 @@ interface DashKitProps { - **onItemEdit**: Appelée lorsque vous cliquez pour éditer un widget. - **onChange**: Appelée lorsque la configuration ou [itemsStateAndParams](#itemsStateAndParams) sont modifiés. - **onDrop**: Appelée lorsqu'un élément est déposé depuis ActionPanel via (#DashKitDnDWrapper) -- **onItemMountChange**: Appelée lorsque l'état de montage d'un élément change -- **onItemRender**: Appelée lorsque le rendu d'un élément est terminé +- **onItemMountChange**: Appelée lorsque l'état de montage d'un élément change. +- **onItemRender**: Appelée lorsque le rendu d'un élément est terminé. - **defaultGlobalParams**, **globalParams**: [Paramètres](#Params) qui affectent tous les widgets. Dans DataLens, `defaultGlobalParams` sont les paramètres globaux définis dans les paramètres du tableau de bord. `globalParams` sont les paramètres globaux qui peuvent être définis dans l'URL. - **itemsStateAndParams**: [itemsStateAndParams](#itemsStateAndParams). - **settings**: Paramètres de DashKit. - **context**: Objet qui sera transmis à tous les widgets. -- **overlayControls**: Objet qui remplace les contrôles du widget au moment de l'édition. Si non transmis, les contrôles de base seront affichés. Si `null` est passé, seul le bouton de fermeture ou un menu personnalisé sera affiché. -- **overlayMenuItems**: Éléments de menu déroulant personnalisés -- **noOverlay**: Si `true`, la superposition et les contrôles ne sont pas affichés pendant l'édition. +- **overlayControls**: Objet qui remplace les contrôles du widget au moment de l'édition. S'il n'est pas transmis, les contrôles de base seront affichés. Si `null` est passé, seul le bouton de fermeture ou un menu personnalisé sera affiché. +- **overlayMenuItems**: Éléments de menu déroulant personnalisés. +- **noOverlay**: Si `true`, l'overlay et les contrôles ne sont pas affichés pendant l'édition. - **focusable**: Si `true`, les éléments de la grille seront focusables. - **onItemFocus**: Appelée lorsque `focusable` est vrai et que l'élément est focusé. - **onItemBlur**: Appelée lorsque `focusable` est vrai et que l'élément perd le focus. - **draggableHandleClassName** : Nom de la classe CSS de l'élément qui rend le widget déplaçable. -- **onDragStart**: Appelée par ReactGridLayout lorsque le déplacement d'un élément commence -- **onDrag**: Appelée par ReactGridLayout pendant le déplacement d'un élément -- **onDragStop**: Appelée par ReactGridLayout lorsque le déplacement d'un élément s'arrête -- **onResizeStart**: Appelée par ReactGridLayout lorsque le redimensionnement d'un élément commence -- **onResize**: Appelée par ReactGridLayout pendant le redimensionnement d'un élément -- **onResizeStop**: Appelée par ReactGridLayout lorsque le redimensionnement d'un élément s'arrête -- **getPreparedCopyItemOptions**: Appelée pour convertir un élément copié en objet sérialisable avant de l'enregistrer dans le localStorage. Elle doit être utilisée à la place de la prop obsolète `context.getPreparedCopyItemOptions` -- **onCopyFulfill**: Appelée lorsque la copie d'un élément est terminée avec `error=null` et `data` défini en cas de succès, et avec `error: Error` sans `data` sinon +- **onDragStart**: Appelée par ReactGridLayout lorsque le déplacement d'un élément commence. +- **onDrag**: Appelée par ReactGridLayout pendant le déplacement d'un élément. +- **onDragStop**: Appelée par ReactGridLayout lorsque le déplacement d'un élément s'arrête. +- **onResizeStart**: Appelée par ReactGridLayout lorsque le redimensionnement d'un élément commence. +- **onResize**: Appelée par ReactGridLayout pendant le redimensionnement d'un élément. +- **onResizeStop**: Appelée par ReactGridLayout lorsque le redimensionnement d'un élément s'arrête. +- **getPreparedCopyItemOptions**: Appelée pour convertir un élément copié en objet sérialisable avant de l'enregistrer dans le localStorage. Elle doit être utilisée à la place de la prop dépréciée `context.getPreparedCopyItemOptions`. +- **onCopyFulfill**: Appelée lorsque la copie d'un élément est terminée avec `error=null` et `data` défini en cas de succès, et avec `error: Error` sans `data` sinon. ## Utilisation ### Configuration de DashKit -Avant d'utiliser `DashKit` en tant que composant React, il doit être configuré. +Avant d'utiliser `DashKit` comme composant React, il doit être configuré. - Définir la langue @@ -111,7 +111,7 @@ Avant d'utiliser `DashKit` en tant que composant React, il doit être configuré - DashKit.setSettings - Utilisé pour les paramètres globaux de DashKit (tels que les marges entre les widgets, les tailles de widgets par défaut et le menu de superposition des widgets) + Utilisé pour les paramètres globaux de DashKit (tels que les marges entre les widgets, les tailles par défaut des widgets et le menu d'overlay des widgets). ```js import {DashKit} from '@gravity-ui/dashkit'; @@ -125,7 +125,7 @@ Avant d'utiliser `DashKit` en tant que composant React, il doit être configuré - DashKit.registerPlugins - Enregistrement et configuration des plugins + Enregistrement et configuration des plugins. ```js import {DashKit} from '@gravity-ui/dashkit'; @@ -156,8 +156,8 @@ Avant d'utiliser `DashKit` en tant que composant React, il doit être configuré ```ts export interface Config { - salt: string; // pour former un ID unique - counter: number; // pour former un ID unique, ne fait qu'augmenter + salt: string; // pour former un identifiant unique + counter: number; // pour former un identifiant unique, ne fait qu'augmenter items: ConfigItem[]; // états initiaux des widgets layout: ConfigLayout[]; // position des widgets sur la grille https://github.com/react-grid-layout aliases: ConfigAliases; // alias pour les paramètres voir #Params @@ -277,7 +277,7 @@ const newConfig = DashKit.setItem({ }, namespace: 'default', type: 'text', - // Optionnel. Si un nouvel élément doit être inséré dans la disposition actuelle avec des dimensions prédéfinies + // Optionnel. Si le nouvel élément doit être inséré dans la disposition actuelle avec des dimensions prédéfinies layout: { // L'élément actuel est inséré avant 'Ea' h: 6, w: 12, @@ -287,7 +287,7 @@ const newConfig = DashKit.setItem({ }, config: config, options: { - // Optionnel. Nouvelles valeurs de disposition pour les éléments existants lorsqu'un nouvel élément est déposé depuis l'ActionPanel + // Optionnel. Nouvelles valeurs de disposition pour les éléments existants lorsqu'un nouvel élément est déposé depuis le panneau d'actions updateLayout: newLayout, }, }); @@ -368,22 +368,96 @@ interface ItemsStateAndParamsBase { type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase; ``` +### Événements expérimentaux de DashKit + +> Expérimental : cette API peut changer dans les versions mineures. + +`DashKit` expose une API d'événements d'instance expérimentale. Utilisez une référence de composant et abonnez-vous avec `dashkitRef.current?.on(eventName, handler)`. La méthode renvoie une fonction de rappel de désabonnement. + +Le premier événement pris en charge est `change`. Il est émis lorsque la disposition change, avant que `onChange` ne soit appelé. Le gestionnaire peut lire les dispositions complètes suivante et précédente, lire les correctifs de disposition ou appeler `preventDefault()` pour arrêter l'appel `onChange` par défaut. + +```tsx +import React from 'react'; +import {DashKit} from '@gravity-ui/dashkit'; +import type {DashKitChangeEvent} from '@gravity-ui/dashkit'; + +function Dashboard() { + const dashkitRef = React.useRef(null); + + React.useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event: DashKitChangeEvent) => { + console.log(event.patches); + + if (event.patches.length > 0) { + event.preventDefault(); + } + }); + + return () => unsubscribe?.(); + }, []); + + return ; +} +``` + +```ts +type DashKitLayoutPatch = Pick & + Partial>; + +type DashKitChangeEvent = { + patches: DashKitLayoutPatch[]; + layout: ConfigLayout[]; + previousLayout: ConfigLayout[]; + preventDefault: () => void; + readonly defaultPrevented: boolean; +}; +``` + +#### Mises à jour de la disposition pilotées par les événements + +Si vous utilisez `preventDefault()` dans le gestionnaire d'événements `change`, vous pouvez désormais gérer les mises à jour de la disposition sans réinitialiser la prop `config`. DashKit maintient une référence interne et calcule les correctifs de manière incrémentielle : + +```tsx +function Dashboard() { + const [config, setConfig] = useState(initialConfig); + const dashkitRef = useRef(null); + + useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event) => { + event.preventDefault(); // Ne pas appeler onChange + + // Envoyez uniquement les correctifs incrémentiels à votre backend + sendPatches(event.patches); + + // Pas besoin d'appeler setConfig({ ...config, layout: event.layout }) + // DashKit maintient l'état visuel en interne + }); + + return unsubscribe; + }, []); + + return {}} />; +} +``` + +**Important :** Si vous mettez à jour `config.layout` ultérieurement à partir des props (par exemple, à partir d'une synchronisation serveur), DashKit réinitialisera sa référence interne pour correspondre à la nouvelle prop. Cela garantit la compatibilité avec les flux de travail pilotés par les événements et contrôlés. + ### Menu -Vous pouvez spécifier un menu personnalisé pour les superpositions de widgets DashKit en mode édition. +Vous pouvez spécifier un menu de superposition de widgets DashKit personnalisé en mode édition. ```ts type MenuItem = { - id: string; // id unique - title?: string; // titre de la chaîne - icon?: ReactNode; // nœud de l'icône - iconSize?: number | string; // taille de l'icône en px sous forme de nombre ou de chaîne avec unités + id: string; // identifiant unique + title?: string; // titre textuel + icon?: ReactNode; // nœud d'icône + iconSize?: number | string; // taille de l'icône en px, en nombre ou en chaîne avec unités handler?: (item: ConfigItem) => void; // gestionnaire d'action personnalisé pour l'élément visible?: (item: ConfigItem) => boolean; // gestionnaire de visibilité optionnel pour filtrer les éléments du menu className?: string; // propriété de classe personnalisée }; -// utiliser un tableau d'éléments de menu dans les paramètres +// utilisez un tableau d'éléments de menu dans les paramètres | null} /> [obsolète] @@ -391,7 +465,7 @@ type MenuItem = { DashKit.setSettings({menu: [] as Array}); ``` -### Éléments déplaçables depuis l'ActionPanel +### Éléments déplaçables depuis ActionPanel #### DashKitDnDWrapper @@ -408,35 +482,38 @@ interface DashKitDnDWrapperProps { dragImageSrc?: string; onDragStart?: (dragProps: ItemDragProps) => void; onDragEnd?: () => void; - onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) => void | boolean; + onDropDragOver?: ( + draggedItem: DraggedOverItem, + sharedItem: DraggedOverItem | null, + ) => void | boolean; } ``` -- **dragImageSrc**: Aperçu de l'image de glisser-déposer, par défaut une image png transparente de 1px en base64 est utilisée. -- **onDragStart**: Callback appelé lorsqu'un élément est glissé depuis l'ActionPanel. -- **onDragEnd**: Callback appelé lorsqu'un élément est déposé ou que le glisser-déposer est annulé. +- **dragImageSrc** : Aperçu de l'image de glisser-déposer. Par défaut, une image PNG transparente de 1px en base64 est utilisée. +- **onDragStart** : Callback appelé lorsqu'un élément est glissé depuis ActionPanel. +- **onDragEnd** : Callback appelé lorsqu'un élément est déposé ou que le glisser-déposer est annulé. ```ts type ItemDragProps = { - type: string; // Type de plugin - layout?: { // Optionnel. Taille de l'élément pour l'aperçu et l'initialisation - w?: number; - h?: number; - }; - extra?: any; // Contexte utilisateur personnalisé + type: string; // Type de plugin + layout?: { + // Optionnel. Taille de l'élément de disposition pour l'aperçu et l'initialisation + w?: number; + h?: number; + }; + extra?: any; // Contexte utilisateur personnalisé }; ``` ```ts type ItemDropProps = { - commit: () => void; // Le callback doit être appelé après que toutes les opérations de configuration soient effectuées - dragProps: ItemDragProps; // Propriétés de glisser-déposer de l'élément - itemLayout: ConfigLayout; // Dimensions calculées de la disposition de l'élément - newLayout: ConfigLayout[]; // Nouvelle disposition après le dépôt de l'élément + commit: () => void; // Callback à appeler après toutes les opérations de configuration effectuées + dragProps: ItemDragProps; // Props de glisser-déposer de l'élément + itemLayout: ConfigLayout; // Dimensions de l'élément calculées + newLayout: ConfigLayout[]; // Nouvelle disposition après le dépôt de l'élément }; ``` - #### Exemple : ```jsx @@ -453,7 +530,7 @@ const overlayMenuItems = [ ] const onDrop = (dropProps: ItemDropProps) => { - // ... ajouter l'élément à votre configuration + // ... ajoutez l'élément à votre configuration dropProps.commit(); } @@ -467,24 +544,24 @@ const onDrop = (dropProps: ItemDropProps) => { | Nom | Description | | :--------------------------------------------- | :-------------------- | -| Variables du panneau d'actions | | -| `--dashkit-action-panel-color` | Couleur de fond | -| `--dashkit-action-panel-border-color` | Couleur de bordure | -| `--dashkit-action-panel-border-radius` | Rayon de bordure | -| Variables des éléments du panneau d'actions | | +| Variables du panneau d'action | | +| `--dashkit-action-panel-color` | Couleur de fond | +| `--dashkit-action-panel-border-color` | Couleur de la bordure | +| `--dashkit-action-panel-border-radius` | Rayon de la bordure | +| Variables des éléments du panneau d'action | | | `--dashkit-action-panel-item-color` | Couleur de fond | -| `--dashkit-action-panel-item-text-color` | Couleur du texte | +| `--dashkit-action-panel-item-text-color` | Couleur du texte | | `--dashkit-action-panel-item-color-hover` | Couleur de fond au survol | -| `--dashkit-action-panel-item-text-color-hover` | Couleur du texte au survol | -| Variables de la surcouche | | -| `--dashkit-overlay-border-color` | Couleur de bordure | -| `--dashkit-overlay-color` | Couleur de fond | +| `--dashkit-action-panel-item-text-color-hover` | Couleur du texte au survol | +| Variables de superposition | | +| `--dashkit-overlay-border-color` | Couleur de la bordure | +| `--dashkit-overlay-color` | Couleur de fond | | `--dashkit-overlay-opacity` | Opacité | -| Variables des éléments de la grille | | +| Variables des éléments de la grille | | | `--dashkit-grid-item-edit-opacity` | Opacité | -| `--dashkit-grid-item-border-radius` | Rayon de bordure | -| Variables des espaces réservés | | -| `--dashkit-placeholder-color` | Couleur de fond | +| `--dashkit-grid-item-border-radius` | Rayon de la bordure | +| Variables des espaces réservés | | +| `--dashkit-placeholder-color` | Couleur de fond | | `--dashkit-placeholder-opacity` | Opacité | #### Exemple d'utilisation @@ -522,15 +599,14 @@ const CustomThemeWrapper = (props: { ### Compilation et surveillance -- Compiler les dépendances `npm ci` -- Compiler le projet `npm run build` -- Compiler le storybook `npm run start` - -Par défaut, le storybook s'exécute sur `http://localhost:7120/`. -Les nouveaux changements du projet ne sont pas toujours pris en compte lorsque le storybook est en cours d'exécution, il est donc préférable de recompiler le projet manuellement et de redémarrer le storybook. +- Compilation des dépendances `npm ci` +- Compilation du projet `npm run build` +- Compilation de Storybook `npm run start` +Par défaut, Storybook s'exécute sur `http://localhost:7120/`. +Les modifications apportées au projet ne sont pas toujours prises en compte lorsque Storybook est en cours d'exécution. Il est donc préférable de recompiler le projet manuellement et de redémarrer Storybook. -### Exemple de configuration nginx pour le développement sur une machine de développement +### Exemple de configuration Nginx pour le développement sur une machine de développement ```bash server { diff --git a/src/content/local-docs/libs/dashkit/README-ja.md b/src/content/local-docs/libs/dashkit/README-ja.md index 83d11f858371..c36dd5d71207 100644 --- a/src/content/local-docs/libs/dashkit/README-ja.md +++ b/src/content/local-docs/libs/dashkit/README-ja.md @@ -2,7 +2,7 @@ # DashKit -ダッシュボードグリッドレンダリングライブラリです。 +ダッシュボードグリッド描画ライブラリです。 ## インストール @@ -12,7 +12,7 @@ npm i @gravity-ui/dashkit @gravity-ui/uikit ## 説明 -このライブラリは、ウィジェットをグリッド上に配置し、サイズ変更、追加、削除するために使用されます。 +このライブラリは、ウィジェットをグリッド上に配置し、リサイズ、追加、削除するために使用されます。 ウィジェットはReactコンポーネントです。例えば、テキスト、グラフィック、画像などです。 新しいウィジェットはプラグインシステムを通じて追加されます。 @@ -25,12 +25,12 @@ npm i @gravity-ui/dashkit @gravity-ui/uikit ```ts type ItemManipulationCallback = (eventData: { - layout: Layout[]; - oldItem: Layout; - newItem: Layout; - placeholder: Layout; - e: MouseEvent; - element: HTMLElement; + layout: Layout[]; + oldItem: Layout; + newItem: Layout; + placeholder: Layout; + e: MouseEvent; + element: HTMLElement; }) => void; interface DashKitProps { @@ -68,38 +68,38 @@ interface DashKitProps { } ``` -- **config**: [сonfig](#Config)。 +- **config**: [Config](#Config)です。 - **editMode**: 編集モードが有効かどうか。 - **onItemEdit**: ウィジェットの編集をクリックしたときに呼び出されます。 - **onChange**: configまたは[itemsStateAndParams](#itemsStateAndParams)が変更されたときに呼び出されます。 - **onDrop**: ActionPanelから(#DashKitDnDWrapper)を使用してアイテムがドロップされたときに呼び出されます。 - **onItemMountChange**: アイテムのマウント状態が変更されたときに呼び出されます。 - **onItemRender**: アイテムのレンダリングが完了したときに呼び出されます。 -- **defaultGlobalParams**, **globalParams**: すべてのウィジェットに影響する[パラメータ](#Params)。DataLensでは、`defaultGlobalParams`はダッシュボード設定で設定されたグローバルパラメータです。`globalParams`はURLで設定できるグローバルパラメータです。 -- **itemsStateAndParams**: [itemsStateAndParams](#itemsStateAndParams)。 -- **settings**: DashKitの設定。 -- **context**: すべてのウィジェットにプロップとして渡されるオブジェクト。 -- **overlayControls**: 編集時にウィジェットコントロールをオーバーライドするオブジェクト。渡されない場合は、基本的なコントロールが表示されます。`null`が渡された場合は、閉じるボタンまたはカスタムメニューのみが表示されます。 -- **overlayMenuItems**: カスタムドロップダウンメニューアイテム。 +- **defaultGlobalParams**, **globalParams**: すべてのウィジェットに影響を与える[パラメータ](#Params)です。DataLensでは、`defaultGlobalParams`はダッシュボード設定でグローバルに設定されたパラメータです。`globalParams`はURLで設定できるグローバルパラメータです。 +- **itemsStateAndParams**: [itemsStateAndParams](#itemsStateAndParams)です。 +- **settings**: DashKitの設定です。 +- **context**: すべてのウィジェットにプロップとして渡されるオブジェクトです。 +- **overlayControls**: 編集時にウィジェットコントロールをオーバーライドするオブジェクトです。指定しない場合は、基本的なコントロールが表示されます。`null`を渡すと、閉じるボタンまたはカスタムメニューのみが表示されます。 +- **overlayMenuItems**: カスタムドロップダウンメニュー項目です。 - **noOverlay**: `true`の場合、編集中はオーバーレイとコントロールが表示されません。 - **focusable**: `true`の場合、グリッドアイテムはフォーカス可能になります。 - **onItemFocus**: `focusable`が`true`でアイテムがフォーカスされたときに呼び出されます。 - **onItemBlur**: `focusable`が`true`でアイテムからフォーカスが外れたときに呼び出されます。 -- **draggableHandleClassName**: ウィジェットをドラッグ可能にする要素のCSSクラス名。 +- **draggableHandleClassName**: ウィジェットをドラッグ可能にする要素のCSSクラス名です。 - **onDragStart**: アイテムのドラッグが開始されたときにReactGridLayoutによって呼び出されます。 - **onDrag**: アイテムのドラッグ中にReactGridLayoutによって呼び出されます。 - **onDragStop**: アイテムのドラッグが停止したときにReactGridLayoutによって呼び出されます。 - **onResizeStart**: アイテムのリサイズが開始されたときにReactGridLayoutによって呼び出されます。 - **onResize**: アイテムのリサイズ中にReactGridLayoutによって呼び出されます。 - **onResizeStop**: アイテムのリサイズが停止したときにReactGridLayoutによって呼び出されます。 -- **getPreparedCopyItemOptions**: ローカルストレージに保存する前に、コピーされたアイテムをシリアライズ可能なオブジェクトに変換するために呼び出されます。非推奨の`context.getPreparedCopyItemOptions`プロップの代わりにこれを使用する必要があります。 -- **onCopyFulfill**: アイテムのコピーが完了したときに、成功した場合は`error=null`と`data`が定義され、それ以外の場合は`error: Error`なしで`data`なしで呼び出されます。 +- **getPreparedCopyItemOptions**: ローカルストレージに保存する前に、コピーされたアイテムをシリアライズ可能なオブジェクトに変換するために呼び出されます。非推奨の`context.getPreparedCopyItemOptions`プロップの代わりにこれを使用してください。 +- **onCopyFulfill**: アイテムのコピーが完了したときに、成功した場合は`error=null`と`data`が定義され、それ以外の場合は`data`なしで`error: Error`とともに呼び出されます。 ## 使用方法 ### DashKitの設定 -`DashKit`をReactコンポーネントとして使用する前に、設定する必要があります。 +`DashKit`をReactコンポーネントとして使用する前に、設定が必要です。 - 言語を設定する @@ -156,12 +156,12 @@ interface DashKitProps { ```ts export interface Config { - salt: string; // 一意のIDを形成するため - counter: number; // 一意のIDを形成するため、増加し続けます + salt: string; // 一意のIDを形成するためのもの + counter: number; // 一意のIDを形成するためのもの、増加し続ける items: ConfigItem[]; // 初期ウィジェットの状態 layout: ConfigLayout[]; // グリッド上のウィジェットの位置 https://github.com/react-grid-layout - aliases: ConfigAliases; // パラメータのエイリアス #Params を参照 - connections: ConfigConnection[]; // ウィジェット間のリンク #Params を参照 + aliases: ConfigAliases; // パラメータのエイリアス #Params参照 + connections: ConfigConnection[]; // ウィジェット間のリンク #Params参照 } ``` @@ -180,7 +180,7 @@ const config: DashKitProps['config'] = { id: 'tT', data: { size: 'm', - text: 'キャプション', + text: 'Caption', showInTOC: true, }, type: 'title', @@ -199,7 +199,7 @@ const config: DashKitProps['config'] = { { id: 'zR', data: { - text: '### テキスト', + text: '### Text', }, type: 'text', namespace: 'default', @@ -277,8 +277,8 @@ const newConfig = DashKit.setItem({ }, namespace: 'default', type: 'text', - // オプション。新しいアイテムを定義済みのディメンションで現在のレイアウトに挿入する必要がある場合 - layout: { // 現在のアイテムは 'Ea' の前に挿入されます + // Optional. If new item needed to be inserted in current layout with predefined dimensions + layout: { // Current item inseterted before 'Ea' h: 6, w: 12, x: 0, @@ -287,13 +287,13 @@ const newConfig = DashKit.setItem({ }, config: config, options: { - // オプション。ActionPanelからドロップされたときに既存のアイテムの新しいレイアウト値 + // Optional. New layout values for existing items when new element is dropped from ActionPanel updateLayout: newLayout, }, }); ``` -config内の既存のアイテムを変更する: +config内の既存アイテムを変更する: ```ts const newConfig = DashKit.setItem({ @@ -301,7 +301,7 @@ const newConfig = DashKit.setItem({ id: 'tT', // item.id data: { size: 'm', - text: `新しいキャプション`, + text: `New caption`, }, namespace: 'default', type: 'title', @@ -324,7 +324,7 @@ const {config: newConfig, itemsStateAndParams} = DashKit.removeItem({ }); ``` -### パラメータ +### Params ```ts type Params = Record; @@ -335,9 +335,9 @@ type Params = Record; 生成順序: 1. `defaultGlobalParams` -2. デフォルトのウィジェットパラメータ `item.default` +2. デフォルトウィジェットパラメータ `item.default` 3. `globalParams` -4. [itemsStateAndParams](#itemsStateAndParams) からのパラメータ(キューに従って)。 +4. キューに従った [itemsStateAndParams](#itemsStateAndParams) からのパラメータ。 ### itemsStateAndParams @@ -347,8 +347,8 @@ type Params = Record; ```ts interface StateAndParamsMeta = { __meta__: { - queue: {id: string}[]; // キュー - version: number; // itemsStateAndParams の現在のバージョン + queue: {id: string}[]; // queue + version: number; // current version itemsStateAndParams }; } ``` @@ -368,16 +368,90 @@ interface ItemsStateAndParamsBase { type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase; ``` +### Experimental DashKit events + +> Experimental: this API can change in minor releases. + +`DashKit` は、実験的なインスタンスイベント API を公開します。コンポーネントの ref を使用し、`dashkitRef.current?.on(eventName, handler)` で購読します。このメソッドは、アンサブスクライブコールバックを返します。 + +最初にサポートされるイベントは `change` です。これは、レイアウトが変更されたときに、`onChange` が呼び出される前に発行されます。ハンドラは、次のレイアウトと前のレイアウト全体を読み取ったり、レイアウトパッチを読み取ったり、`preventDefault()` を呼び出してデフォルトの `onChange` 呼び出しを停止したりできます。 + +```tsx +import React from 'react'; +import {DashKit} from '@gravity-ui/dashkit'; +import type {DashKitChangeEvent} from '@gravity-ui/dashkit'; + +function Dashboard() { + const dashkitRef = React.useRef(null); + + React.useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event: DashKitChangeEvent) => { + console.log(event.patches); + + if (event.patches.length > 0) { + event.preventDefault(); + } + }); + + return () => unsubscribe?.(); + }, []); + + return ; +} +``` + +```ts +type DashKitLayoutPatch = Pick & + Partial>; + +type DashKitChangeEvent = { + patches: DashKitLayoutPatch[]; + layout: ConfigLayout[]; + previousLayout: ConfigLayout[]; + preventDefault: () => void; + readonly defaultPrevented: boolean; +}; +``` + +#### Event-driven layout updates + +`preventDefault()` を `change` イベントハンドラで使用すると、`config` プロップを再初期化せずにレイアウトの更新を処理できるようになりました。DashKit は内部的にベースラインを維持し、パッチを段階的に計算します。 + +```tsx +function Dashboard() { + const [config, setConfig] = useState(initialConfig); + const dashkitRef = useRef(null); + + useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event) => { + event.preventDefault(); // onChange を呼び出さない + + // インクリメンタルなパッチのみをバックエンドに送信します + sendPatches(event.patches); + + // setConfig({ ...config, layout: event.layout }) を呼び出す必要はありません + // DashKit はビジュアル状態を内部で維持します + }); + + return unsubscribe; + }, []); + + return {}} />; +} +``` + +**重要:** 後でプロップから `config.layout` を更新した場合(例: サーバー同期から)、DashKit は新しいプロップと一致するように内部ベースラインをリセットします。これにより、イベント駆動型ワークフローと制御型ワークフローの両方との互換性が確保されます。 + ### メニュー -編集モードでは、カスタムの DashKit ウィジェットオーバーレイメニューを指定できます。 +編集モードでカスタム DashKit ウィジェットオーバーレイメニューを指定できます。 ```ts type MenuItem = { - id: string; // ユニークなID + id: string; // 一意のID title?: string; // 文字列タイトル icon?: ReactNode; // アイコンのノード - iconSize?: number | string; // アイコンサイズ(px単位の数値または単位付き文字列) + iconSize?: number | string; // px単位のアイコンサイズ(数値または単位付き文字列) handler?: (item: ConfigItem) => void; // カスタムアイテムのアクションハンドラ visible?: (item: ConfigItem) => boolean; // メニューアイテムをフィルタリングするためのオプションの表示ハンドラ className?: string; // カスタムクラスプロパティ @@ -387,7 +461,7 @@ type MenuItem = { | null} /> [非推奨] -// overlayMenuItems プロパティは setSettings メニューよりも優先されます +// overlayMenuItems プロパティは setSettings のメニューよりも優先されます DashKit.setSettings({menu: [] as Array}); ``` @@ -405,38 +479,41 @@ type DraggedOverItem = { }; interface DashKitDnDWrapperProps { - dragImageSrc?: string; - onDragStart?: (dragProps: ItemDragProps) => void; - onDragEnd?: () => void; - onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) => void | boolean; + dragImageSrc?: string; // ドラッグ画像プレビュー。デフォルトでは透明な1px PNG base64 が使用されます。 + onDragStart?: (dragProps: ItemDragProps) => void; // ActionPanel から要素がドラッグされたときに呼び出されるコールバック + onDragEnd?: () => void; // 要素がドロップされたか、ドラッグがキャンセルされたときに呼び出されるコールバック + onDropDragOver?: ( + draggedItem: DraggedOverItem, + sharedItem: DraggedOverItem | null, + ) => void | boolean; } ``` -- **dragImageSrc**: ドラッグ画像のプレビュー。デフォルトでは、透明な1px PNGのbase64が使用されます。 -- **onDragStart**: ActionPanelから要素がドラッグされたときに呼び出されるコールバック。 +- **dragImageSrc**: ドラッグ画像プレビュー。デフォルトでは透明な1px PNG base64 が使用されます。 +- **onDragStart**: ActionPanel から要素がドラッグされたときに呼び出されるコールバック。 - **onDragEnd**: 要素がドロップされたか、ドラッグがキャンセルされたときに呼び出されるコールバック。 ```ts type ItemDragProps = { - type: string; // プラグインのタイプ - layout?: { // オプション。プレビューと初期化のためのレイアウトアイテムのサイズ - w?: number; - h?: number; - }; - extra?: any; // カスタムユーザーコンテキスト + type: string; // プラグインタイプ + layout?: { + // オプション。プレビューと初期化のためのレイアウトアイテムサイズ + w?: number; + h?: number; + }; + extra?: any; // カスタムユーザーコンテキスト }; ``` ```ts type ItemDropProps = { - commit: () => void; // すべての設定操作が完了した後、コールバックを呼び出す必要があります - dragProps: ItemDragProps; // アイテムのドラッグプロパティ - itemLayout: ConfigLayout; // 計算されたアイテムのレイアウト寸法 - newLayout: ConfigLayout[]; // 要素がドロップされた後の新しいレイアウト + commit: () => void; // すべての設定操作が完了した後、呼び出す必要があるコールバック + dragProps: ItemDragProps; // アイテムのドラッグプロップ + itemLayout: ConfigLayout; // 計算されたアイテムのレイアウト寸法 + newLayout: ConfigLayout[]; // 要素がドロップされた後の新しいレイアウト }; ``` - #### 例: ```jsx @@ -447,13 +524,13 @@ const overlayMenuItems = [ title: 'Chart', qa: 'chart', dragProps: { // ItemDragProps - type: 'custom', // 登録されたプラグインタイプ + type: 'custom', // 登録済みのプラグインタイプ }, } ] const onDrop = (dropProps: ItemDropProps) => { - // ... 要素を構成に追加します + // ... 要素をconfigに追加します dropProps.commit(); } @@ -467,23 +544,23 @@ const onDrop = (dropProps: ItemDropProps) => { | 名前 | 説明 | | :--------------------------------------------- | :------------- | -| Action panel variables | | +| アクションパネル変数 | | | `--dashkit-action-panel-color` | 背景色 | | `--dashkit-action-panel-border-color` | ボーダーの色 | -| `--dashkit-action-panel-border-radius` | ボーダーの半径 | -| Action panel item variables | | +| `--dashkit-action-panel-border-radius` | ボーダー半径 | +| アクションパネルアイテム変数 | | | `--dashkit-action-panel-item-color` | 背景色 | | `--dashkit-action-panel-item-text-color` | テキストの色 | | `--dashkit-action-panel-item-color-hover` | ホバー時の背景色 | -| `--dashkit-action-panel-item-text-color-hover` | ホバー時のテキストの色 | -| Overlay variables | | +| `--dashkit-action-panel-item-text-color-hover` | ホバー時のテキスト色 | +| オーバーレイ変数 | | | `--dashkit-overlay-border-color` | ボーダーの色 | | `--dashkit-overlay-color` | 背景色 | | `--dashkit-overlay-opacity` | 不透明度 | -| Grid item variables | | +| グリッドアイテム変数 | | | `--dashkit-grid-item-edit-opacity` | 不透明度 | -| `--dashkit-grid-item-border-radius` | ボーダーの半径 | -| Placeholder variables | | +| `--dashkit-grid-item-border-radius` | ボーダー半径 | +| プレースホルダー変数 | | | `--dashkit-placeholder-color` | 背景色 | | `--dashkit-placeholder-opacity` | 不透明度 | @@ -520,15 +597,14 @@ const CustomThemeWrapper = (props: { ## 開発 -### ビルドと監視 +### ビルドとウォッチ - 依存関係のビルド `npm ci` - プロジェクトのビルド `npm run build` - Storybook のビルド `npm run start` デフォルトでは、Storybook は `http://localhost:7120/` で実行されます。 -Storybook を実行中にプロジェクトの変更が常に反映されるとは限らないため、プロジェクトを手動で再ビルドして Storybook を再起動することをお勧めします。 - +Storybook を実行中にプロジェクトの変更が常に反映されるとは限らないため、手動でプロジェクトを再ビルドし、Storybook を再起動することをお勧めします。 ### 開発マシンでの開発用 nginx 設定例 diff --git a/src/content/local-docs/libs/dashkit/README-ko.md b/src/content/local-docs/libs/dashkit/README-ko.md index 471d043ac023..8d0f2432c4e0 100644 --- a/src/content/local-docs/libs/dashkit/README-ko.md +++ b/src/content/local-docs/libs/dashkit/README-ko.md @@ -12,10 +12,10 @@ npm i @gravity-ui/dashkit @gravity-ui/uikit ## 설명 -이 라이브러리는 위젯을 그리드에 정렬하고, 크기를 조절하며, 새 위젯을 추가하거나 삭제하는 데 사용됩니다. -위젯은 React 컴포넌트이며, 텍스트, 그래픽, 이미지 등을 포함할 수 있습니다. +이 라이브러리는 위젯을 그리드에 정렬하고, 크기를 조절하며, 새로 추가하거나 삭제하는 데 사용됩니다. +위젯은 React 컴포넌트입니다. 예를 들어 텍스트, 그래픽, 이미지 등이 있습니다. -새 위젯은 플러그인 시스템을 통해 추가됩니다. +새로운 위젯은 플러그인 시스템을 통해 추가됩니다. ### 플러그인 @@ -25,12 +25,12 @@ npm i @gravity-ui/dashkit @gravity-ui/uikit ```ts type ItemManipulationCallback = (eventData: { - layout: Layout[]; - oldItem: Layout; - newItem: Layout; - placeholder: Layout; - e: MouseEvent; - element: HTMLElement; + layout: Layout[]; + oldItem: Layout; + newItem: Layout; + placeholder: Layout; + e: MouseEvent; + element: HTMLElement; }) => void; interface DashKitProps { @@ -68,32 +68,32 @@ interface DashKitProps { } ``` -- **config**: [config](#Config)입니다. -- **editMode**: 편집 모드 활성화 여부입니다. -- **onItemEdit**: 위젯 편집을 클릭할 때 호출됩니다. -- **onChange**: config 또는 [itemsStateAndParams](#itemsStateAndParams)가 변경될 때 호출됩니다. +- **config**: [설정](#Config)입니다. +- **editMode**: 편집 모드가 활성화되었는지 여부입니다. +- **onItemEdit**: 위젯 편집을 위해 클릭할 때 호출됩니다. +- **onChange**: 설정 또는 [itemsStateAndParams](#itemsStateAndParams)가 변경될 때 호출됩니다. - **onDrop**: ActionPanel에서 (#DashKitDnDWrapper)를 사용하여 항목을 드롭할 때 호출됩니다. - **onItemMountChange**: 항목 마운트 상태가 변경될 때 호출됩니다. - **onItemRender**: 항목 렌더링이 완료될 때 호출됩니다. -- **defaultGlobalParams**, **globalParams**: 모든 위젯에 영향을 미치는 [파라미터](#Params)입니다. DataLens에서 `defaultGlobalParams`는 대시보드 설정에 지정된 전역 파라미터입니다. `globalParams`는 URL에서 설정할 수 있는 전역 파라미터입니다. +- **defaultGlobalParams**, **globalParams**: 모든 위젯에 영향을 미치는 [매개변수](#Params)입니다. DataLens에서 `defaultGlobalParams`는 대시보드 설정에 전역적으로 설정된 매개변수입니다. `globalParams`는 URL에 설정할 수 있는 전역 매개변수입니다. - **itemsStateAndParams**: [itemsStateAndParams](#itemsStateAndParams)입니다. - **settings**: DashKit 설정입니다. - **context**: 모든 위젯에 전달될 객체입니다. - **overlayControls**: 편집 시 위젯 컨트롤을 재정의하는 객체입니다. 전달되지 않으면 기본 컨트롤이 표시됩니다. `null`이 전달되면 닫기 버튼 또는 사용자 정의 메뉴만 표시됩니다. - **overlayMenuItems**: 사용자 정의 드롭다운 메뉴 항목입니다. - **noOverlay**: `true`이면 편집 중에 오버레이 및 컨트롤이 표시되지 않습니다. -- **focusable**: `true`이면 그리드 항목에 포커스를 줄 수 있습니다. +- **focusable**: `true`이면 그리드 항목에 포커스를 맞출 수 있습니다. - **onItemFocus**: `focusable`이 `true`이고 항목에 포커스가 맞춰질 때 호출됩니다. - **onItemBlur**: `focusable`이 `true`이고 항목에서 포커스가 해제될 때 호출됩니다. - **draggableHandleClassName**: 위젯을 드래그 가능하게 만드는 요소의 CSS 클래스 이름입니다. -- **onDragStart**: 항목 드래그 시작 시 ReactGridLayout에서 호출됩니다. +- **onDragStart**: 항목 드래그가 시작될 때 ReactGridLayout에서 호출됩니다. - **onDrag**: 항목 드래그 중에 ReactGridLayout에서 호출됩니다. -- **onDragStop**: 항목 드래그 중지 시 ReactGridLayout에서 호출됩니다. -- **onResizeStart**: 항목 크기 조정 시작 시 ReactGridLayout에서 호출됩니다. -- **onResize**: 항목 크기 조정 중에 ReactGridLayout에서 호출됩니다. -- **onResizeStop**: 항목 크기 조정 중지 시 ReactGridLayout에서 호출됩니다. -- **getPreparedCopyItemOptions**: 로컬 스토리지에 저장하기 전에 복사된 항목을 직렬화 가능한 객체로 변환할 때 호출됩니다. 이전에 사용되던 `context.getPreparedCopyItemOptions` prop 대신 사용해야 합니다. -- **onCopyFulfill**: 항목 복사가 성공적으로 완료되면 `error=null` 및 `data`가 정의된 상태로 호출되고, 그렇지 않으면 `data` 없이 `error: Error`와 함께 호출됩니다. +- **onDragStop**: 항목 드래그가 중지될 때 ReactGridLayout에서 호출됩니다. +- **onResizeStart**: 항목 크기 조절이 시작될 때 ReactGridLayout에서 호출됩니다. +- **onResize**: 항목 크기 조절 중에 ReactGridLayout에서 호출됩니다. +- **onResizeStop**: 항목 크기 조절이 중지될 때 ReactGridLayout에서 호출됩니다. +- **getPreparedCopyItemOptions**: 로컬 스토리지에 저장하기 전에 복사된 항목을 직렬화 가능한 객체로 변환할 때 호출됩니다. 비활성화된 `context.getPreparedCopyItemOptions` prop 대신 사용해야 합니다. +- **onCopyFulfill**: 항목 복사가 성공적으로 완료되면 `error=null` 및 `data`가 정의된 상태로 호출되고, 그렇지 않으면 `error: Error`와 함께 `data` 없이 호출됩니다. ## 사용법 @@ -152,7 +152,7 @@ interface DashKitProps { }); ``` -### Config +### 설정 ```ts export interface Config { @@ -160,12 +160,12 @@ export interface Config { counter: number; // 고유 ID 생성을 위한 카운터, 증가만 합니다. items: ConfigItem[]; // 초기 위젯 상태 layout: ConfigLayout[]; // 그리드 상의 위젯 위치 https://github.com/react-grid-layout - aliases: ConfigAliases; // 파라미터 별칭, #Params 참조 - connections: ConfigConnection[]; // 위젯 간 연결, #Params 참조 + aliases: ConfigAliases; // 매개변수 별칭 #Params 참조 + connections: ConfigConnection[]; // 위젯 간 연결 #Params 참조 } ``` -Config 예시: +설정 예시: ```ts import {DashKitProps} from '@gravity-ui/dashkit'; @@ -250,7 +250,7 @@ const config: DashKitProps['config'] = { }; ``` -새로운 항목을 설정에 추가합니다: +새로운 항목을 config에 추가하기: ```ts const newLayout = updateLayout: [ @@ -277,7 +277,7 @@ const newConfig = DashKit.setItem({ }, namespace: 'default', type: 'text', - // 선택 사항. 새 항목이 미리 정의된 차원으로 현재 레이아웃에 삽입되어야 하는 경우 + // 선택 사항. 기존 레이아웃에 새로운 항목을 미리 정의된 크기로 삽입해야 하는 경우 layout: { // 현재 항목이 'Ea' 앞에 삽입됨 h: 6, w: 12, @@ -287,13 +287,13 @@ const newConfig = DashKit.setItem({ }, config: config, options: { - // 선택 사항. 새 요소가 ActionPanel에서 드롭될 때 기존 항목에 대한 새 레이아웃 값 + // 선택 사항. ActionPanel에서 새 요소를 드롭할 때 기존 항목에 대한 새 레이아웃 값 updateLayout: newLayout, }, }); ``` -설정의 기존 항목을 변경합니다: +기존 항목을 config에서 변경하기: ```ts const newConfig = DashKit.setItem({ @@ -310,7 +310,7 @@ const newConfig = DashKit.setItem({ }); ``` -설정에서 항목을 삭제합니다: +config에서 항목 삭제하기: ```ts import {DashKitProps} from '@gravity-ui/dashkit'; @@ -324,20 +324,20 @@ const {config: newConfig, itemsStateAndParams} = DashKit.removeItem({ }); ``` -### 매개변수 +### Params ```ts type Params = Record; ``` -`DashKit`은 위젯, 링크 및 별칭에 대한 기본 매개변수에 따라 매개변수를 생성합니다. 이러한 매개변수는 [ChartKit](https://github.com/gravity-ui/chartkit) 라이브러리에 필요합니다. +`DashKit`는 위젯, 링크 및 별칭에 대한 기본 매개변수에 따라 매개변수를 생성합니다. 이러한 매개변수는 [ChartKit](https://github.com/gravity-ui/chartkit) 라이브러리에 필요합니다. 생성 순서: 1. `defaultGlobalParams` 2. 기본 위젯 매개변수 `item.default` 3. `globalParams` -4. 큐에 따라 [itemsStateAndParams](#itemsStateAndParams)의 매개변수 +4. 큐에 따라 [itemsStateAndParams](#itemsStateAndParams)의 매개변수. ### itemsStateAndParams @@ -368,6 +368,80 @@ interface ItemsStateAndParamsBase { type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase; ``` +### 실험적인 DashKit 이벤트 + +> 실험적: 이 API는 마이너 릴리스에서 변경될 수 있습니다. + +`DashKit`는 실험적인 인스턴스 이벤트 API를 노출합니다. 컴포넌트 ref를 사용하고 `dashkitRef.current?.on(eventName, handler)`로 구독하세요. 이 메서드는 구독 해제 콜백을 반환합니다. + +지원되는 첫 번째 이벤트는 `change`입니다. 레이아웃이 변경될 때 `onChange`가 호출되기 전에 발생합니다. 핸들러는 이전 및 다음 전체 레이아웃을 읽거나, 레이아웃 패치를 읽거나, `preventDefault()`를 호출하여 기본 `onChange` 호출을 중지할 수 있습니다. + +```tsx +import React from 'react'; +import {DashKit} from '@gravity-ui/dashkit'; +import type {DashKitChangeEvent} from '@gravity-ui/dashkit'; + +function Dashboard() { + const dashkitRef = React.useRef(null); + + React.useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event: DashKitChangeEvent) => { + console.log(event.patches); + + if (event.patches.length > 0) { + event.preventDefault(); + } + }); + + return () => unsubscribe?.(); + }, []); + + return ; +} +``` + +```ts +type DashKitLayoutPatch = Pick & + Partial>; + +type DashKitChangeEvent = { + patches: DashKitLayoutPatch[]; + layout: ConfigLayout[]; + previousLayout: ConfigLayout[]; + preventDefault: () => void; + readonly defaultPrevented: boolean; +}; +``` + +#### 이벤트 기반 레이아웃 업데이트 + +`preventDefault()`를 `change` 이벤트 핸들러에서 사용하면, config prop을 다시 초기화하지 않고도 레이아웃 업데이트를 처리할 수 있습니다. DashKit은 내부적으로 기준점을 유지하고 변경 사항을 점진적으로 계산합니다. + +```tsx +function Dashboard() { + const [config, setConfig] = useState(initialConfig); + const dashkitRef = useRef(null); + + useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event) => { + event.preventDefault(); // onChange 호출 방지 + + // 변경된 부분만 백엔드로 전송 + sendPatches(event.patches); + + // setConfig({ ...config, layout: event.layout }) 호출 불필요 + // DashKit이 시각적 상태를 내부적으로 관리합니다. + }); + + return unsubscribe; + }, []); + + return {}} />; +} +``` + +**중요:** 나중에 props에서 `config.layout`을 업데이트하는 경우(예: 서버 동기화), DashKit은 새 prop과 일치하도록 내부 기준점을 재설정합니다. 이는 이벤트 기반 및 제어 워크플로우 모두와의 호환성을 보장합니다. + ### 메뉴 편집 모드에서 사용자 지정 DashKit 위젯 오버레이 메뉴를 지정할 수 있습니다. @@ -377,8 +451,8 @@ type MenuItem = { id: string; // 고유 ID title?: string; // 문자열 제목 icon?: ReactNode; // 아이콘 노드 - iconSize?: number | string; // px 단위 아이콘 크기 (숫자 또는 단위가 있는 문자열) - handler?: (item: ConfigItem) => void; // 사용자 지정 항목 작업 핸들러 + iconSize?: number | string; // px 단위의 숫자 또는 단위가 포함된 문자열로 아이콘 크기 + handler?: (item: ConfigItem) => void; // 사용자 지정 항목 액션 핸들러 visible?: (item: ConfigItem) => boolean; // 메뉴 항목 필터링을 위한 선택적 가시성 핸들러 className?: string; // 사용자 지정 클래스 속성 }; @@ -386,12 +460,12 @@ type MenuItem = { // 설정에서 메뉴 항목 배열 사용 | null} /> -[사용 중단됨] -// overlayMenuItems 속성은 setSettings 메뉴보다 우선 순위가 높습니다. +[deprecated] +// overlayMenuItems 속성은 setSettings 메뉴보다 우선순위가 높습니다. DashKit.setSettings({menu: [] as Array}); ``` -### ActionPanel에서 항목 드래그 +### ActionPanel에서 드래그 가능한 항목 #### DashKitDnDWrapper @@ -405,38 +479,41 @@ type DraggedOverItem = { }; interface DashKitDnDWrapperProps { - dragImageSrc?: string; - onDragStart?: (dragProps: ItemDragProps) => void; - onDragEnd?: () => void; - onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) => void | boolean; + dragImageSrc?: string; // 드래그 이미지 미리보기, 기본값은 투명한 1px png base64 사용 + onDragStart?: (dragProps: ItemDragProps) => void; // ActionPanel에서 요소를 드래그할 때 호출되는 콜백 + onDragEnd?: () => void; // 요소가 드롭되거나 드래그가 취소될 때 호출되는 콜백 + onDropDragOver?: ( + draggedItem: DraggedOverItem, + sharedItem: DraggedOverItem | null, + ) => void | boolean; } ``` -- **dragImageSrc**: 드래그 이미지 미리 보기. 기본적으로 투명한 1px png base64가 사용됩니다. +- **dragImageSrc**: 드래그 이미지 미리보기. 기본적으로 투명한 1px png base64가 사용됩니다. - **onDragStart**: ActionPanel에서 요소를 드래그할 때 호출되는 콜백입니다. -- **onDragEnd**: 요소를 드롭하거나 드래그를 취소할 때 호출되는 콜백입니다. +- **onDragEnd**: 요소가 드롭되거나 드래그가 취소될 때 호출되는 콜백입니다. ```ts type ItemDragProps = { - type: string; // 플러그인 타입 - layout?: { // 선택 사항. 미리보기 및 초기화를 위한 레이아웃 항목 크기 - w?: number; - h?: number; - }; - extra?: any; // 사용자 정의 컨텍스트 + type: string; // 플러그인 유형 + layout?: { + // 선택 사항. 미리보기 및 초기화를 위한 레이아웃 항목 크기 + w?: number; + h?: number; + }; + extra?: any; // 사용자 지정 사용자 컨텍스트 }; ``` ```ts type ItemDropProps = { - commit: () => void; // 모든 구성 작업이 완료된 후 콜백을 호출해야 합니다. - dragProps: ItemDragProps; // 항목 드래그 속성 - itemLayout: ConfigLayout; // 계산된 항목 레이아웃 치수 - newLayout: ConfigLayout[]; // 요소를 드롭한 후의 새 레이아웃 + commit: () => void; // 모든 구성 작업이 완료된 후 호출되어야 하는 콜백 + dragProps: ItemDragProps; // 항목 드래그 속성 + itemLayout: ConfigLayout; // 계산된 항목 레이아웃 치수 + newLayout: ConfigLayout[]; // 요소가 드롭된 후의 새 레이아웃 }; ``` - #### 예시: ```jsx @@ -447,13 +524,13 @@ const overlayMenuItems = [ title: '차트', qa: 'chart', dragProps: { // ItemDragProps - type: 'custom', // 등록된 플러그인 타입 + type: 'custom', // 등록된 플러그인 유형 }, } ] const onDrop = (dropProps: ItemDropProps) => { - // ... 구성에 요소 추가 + // ... 요소를 구성에 추가 dropProps.commit(); } @@ -467,23 +544,23 @@ const onDrop = (dropProps: ItemDropProps) => { | 이름 | 설명 | | :--------------------------------------------- | :------------- | -| Action panel 변수 | | +| 액션 패널 변수 | | | `--dashkit-action-panel-color` | 배경색 | | `--dashkit-action-panel-border-color` | 테두리 색상 | | `--dashkit-action-panel-border-radius` | 테두리 반경 | -| Action panel 항목 변수 | | +| 액션 패널 항목 변수 | | | `--dashkit-action-panel-item-color` | 배경색 | | `--dashkit-action-panel-item-text-color` | 텍스트 색상 | | `--dashkit-action-panel-item-color-hover` | 호버 배경색 | | `--dashkit-action-panel-item-text-color-hover` | 호버 텍스트 색상 | -| Overlay 변수 | | +| 오버레이 변수 | | | `--dashkit-overlay-border-color` | 테두리 색상 | | `--dashkit-overlay-color` | 배경색 | | `--dashkit-overlay-opacity` | 투명도 | -| Grid 항목 변수 | | +| 그리드 항목 변수 | | | `--dashkit-grid-item-edit-opacity` | 투명도 | | `--dashkit-grid-item-border-radius` | 테두리 반경 | -| Placeholder 변수 | | +| 플레이스홀더 변수 | | | `--dashkit-placeholder-color` | 배경색 | | `--dashkit-placeholder-opacity` | 투명도 | @@ -520,17 +597,16 @@ const CustomThemeWrapper = (props: { ## 개발 -### 빌드 및 감시 +### 빌드 및 워치 -- 종속성 빌드 `npm ci` +- 의존성 설치 `npm ci` - 프로젝트 빌드 `npm run build` - 스토리북 빌드 `npm run start` 기본적으로 스토리북은 `http://localhost:7120/`에서 실행됩니다. -스토리북이 실행 중일 때 프로젝트의 새 변경 사항이 항상 반영되지 않을 수 있으므로, 프로젝트를 수동으로 다시 빌드하고 스토리북을 다시 시작하는 것이 좋습니다. - +스토리북이 실행 중일 때 프로젝트의 변경 사항이 항상 반영되지 않을 수 있으므로, 프로젝트를 수동으로 다시 빌드하고 스토리북을 다시 시작하는 것이 좋습니다. -### 개발 머신에서 개발을 위한 nginx 설정 예시 +### 개발 머신에서 개발하기 위한 nginx 설정 예시 ```bash server { diff --git a/src/content/local-docs/libs/dashkit/README-pt.md b/src/content/local-docs/libs/dashkit/README-pt.md index 4bf76d349d2c..1ea3743505cf 100644 --- a/src/content/local-docs/libs/dashkit/README-pt.md +++ b/src/content/local-docs/libs/dashkit/README-pt.md @@ -25,12 +25,12 @@ Plugins são necessários para criar widgets personalizados. ```ts type ItemManipulationCallback = (eventData: { - layout: Layout[]; - oldItem: Layout; - newItem: Layout; - placeholder: Layout; - e: MouseEvent; - element: HTMLElement; + layout: Layout[]; + oldItem: Layout; + newItem: Layout; + placeholder: Layout; + e: MouseEvent; + element: HTMLElement; }) => void; interface DashKitProps { @@ -69,29 +69,29 @@ interface DashKitProps { ``` - **config**: [Config](#Config). -- **editMode**: Se o modo de edição está habilitado. +- **editMode**: Indica se o modo de edição está habilitado. - **onItemEdit**: Chamado quando você clica para editar um widget. - **onChange**: Chamado quando a configuração ou [itemsStateAndParams](#itemsStateAndParams) são alterados. -- **onDrop**: Chamado quando um item é solto do ActionPanel usando (#DashKitDnDWrapper) -- **onItemMountChange**: Chamado quando o estado de montagem do item é alterado -- **onItemRender**: Chamado quando a renderização do item é concluída +- **onDrop**: Chamado quando um item é solto do ActionPanel usando (#DashKitDnDWrapper). +- **onItemMountChange**: Chamado quando o estado de montagem do item é alterado. +- **onItemRender**: Chamado quando a renderização do item é concluída. - **defaultGlobalParams**, **globalParams**: [Parâmetros](#Params) que afetam todos os widgets. No DataLens, `defaultGlobalParams` são parâmetros globais definidos nas configurações do dashboard. `globalParams` são parâmetros globais que podem ser definidos na URL. - **itemsStateAndParams**: [itemsStateAndParams](#itemsStateAndParams). - **settings**: Configurações do DashKit. - **context**: Objeto que será passado para todos os widgets. -- **overlayControls**: Objeto que substitui os controles do widget no momento da edição. Se não for transmitido, controles básicos serão exibidos. Se `null` for passado, apenas o botão de fechar ou um menu personalizado será exibido. -- **overlayMenuItems**: Itens de menu suspensos personalizados +- **overlayControls**: Objeto que substitui os controles do widget durante a edição. Se não for transmitido, controles básicos serão exibidos. Se `null` for passado, apenas o botão de fechar ou um menu personalizado será exibido. +- **overlayMenuItems**: Itens de menu suspensos personalizados. - **noOverlay**: Se `true`, a sobreposição e os controles não são exibidos durante a edição. - **focusable**: Se `true`, os itens da grade serão focáveis. - **onItemFocus**: Chamado quando `focusable` é true e o item recebe foco. - **onItemBlur**: Chamado quando `focusable` é true e o item perde o foco. - **draggableHandleClassName**: Nome da classe CSS do elemento que torna o widget arrastável. -- **onDragStart**: Chamado pelo ReactGridLayout quando o arrasto do item começa -- **onDrag**: Chamado pelo ReactGridLayout durante o arrasto do item -- **onDragStop**: Chamado pelo ReactGridLayout quando o arrasto do item para -- **onResizeStart**: Chamado pelo ReactGridLayout quando o redimensionamento do item começa -- **onResize**: Chamado pelo ReactGridLayout durante o redimensionamento do item -- **onResizeStop**: Chamado pelo ReactGridLayout quando o redimensionamento do item para +- **onDragStart**: Chamado pelo ReactGridLayout quando o arrasto de um item começa. +- **onDrag**: Chamado pelo ReactGridLayout durante o arrasto de um item. +- **onDragStop**: Chamado pelo ReactGridLayout quando o arrasto de um item para. +- **onResizeStart**: Chamado pelo ReactGridLayout quando o redimensionamento de um item começa. +- **onResize**: Chamado pelo ReactGridLayout durante o redimensionamento de um item. +- **onResizeStop**: Chamado pelo ReactGridLayout quando o redimensionamento de um item para. - **getPreparedCopyItemOptions**: Chamado para converter um item copiado em um objeto serializável antes de salvá-lo no localStorage. Deve ser usado em vez da prop depreciada `context.getPreparedCopyItemOptions`. - **onCopyFulfill**: Chamado quando a cópia do item é concluída com `error=null` e `data` definido em caso de sucesso, e com `error: Error` sem `data` caso contrário. @@ -111,7 +111,7 @@ Antes de usar o `DashKit` como um componente React, ele deve ser configurado. - DashKit.setSettings - Usado para configurações globais do DashKit (como margens entre widgets, tamanhos padrão de widgets e menu de sobreposição de widgets) + Usado para configurações globais do DashKit (como margens entre widgets, tamanhos padrão de widgets e menu de sobreposição de widgets). ```js import {DashKit} from '@gravity-ui/dashkit'; @@ -125,7 +125,7 @@ Antes de usar o `DashKit` como um componente React, ele deve ser configurado. - DashKit.registerPlugins - Registrando e configurando plugins + Registro e configuração de plugins. ```js import {DashKit} from '@gravity-ui/dashkit'; @@ -278,7 +278,7 @@ const newConfig = DashKit.setItem({ namespace: 'default', type: 'text', // Opcional. Se o novo item precisar ser inserido no layout atual com dimensões predefinidas - layout: { // Item atual inserido antes de 'Ea' + layout: { // O item atual é inserido antes de 'Ea' h: 6, w: 12, x: 0, @@ -287,7 +287,7 @@ const newConfig = DashKit.setItem({ }, config: config, options: { - // Opcional. Novos valores de layout para itens existentes quando um novo elemento é arrastado do ActionPanel + // Opcional. Novos valores de layout para itens existentes quando um novo elemento é solto do ActionPanel updateLayout: newLayout, }, }); @@ -368,9 +368,83 @@ interface ItemsStateAndParamsBase { type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase; ``` +### Eventos experimentais do DashKit + +> Experimental: esta API pode mudar em lançamentos menores. + +O `DashKit` expõe uma API experimental de eventos de instância. Use uma referência de componente e assine com `dashkitRef.current?.on(eventName, handler)`. O método retorna uma função de callback de cancelamento de inscrição. + +O primeiro evento suportado é `change`. Ele é emitido quando o layout muda, antes que `onChange` seja chamado. O manipulador pode ler os layouts completos, anterior e posterior, ler os patches de layout ou chamar `preventDefault()` para interromper a chamada padrão de `onChange`. + +```tsx +import React from 'react'; +import {DashKit} from '@gravity-ui/dashkit'; +import type {DashKitChangeEvent} from '@gravity-ui/dashkit'; + +function Dashboard() { + const dashkitRef = React.useRef(null); + + React.useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event: DashKitChangeEvent) => { + console.log(event.patches); + + if (event.patches.length > 0) { + event.preventDefault(); + } + }); + + return () => unsubscribe?.(); + }, []); + + return ; +} +``` + +```ts +type DashKitLayoutPatch = Pick & + Partial>; + +type DashKitChangeEvent = { + patches: DashKitLayoutPatch[]; + layout: ConfigLayout[]; + previousLayout: ConfigLayout[]; + preventDefault: () => void; + readonly defaultPrevented: boolean; +}; +``` + +#### Atualizações de layout orientadas a eventos + +Se você usar `preventDefault()` no manipulador de eventos `change`, agora poderá lidar com atualizações de layout sem reinicializar a prop `config`. O DashKit mantém uma linha de base interna e calcula os patches incrementalmente: + +```tsx +function Dashboard() { + const [config, setConfig] = useState(initialConfig); + const dashkitRef = useRef(null); + + useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event) => { + event.preventDefault(); // Não chame onChange + + // Envie apenas os patches incrementais para o seu backend + sendPatches(event.patches); + + // Não é necessário chamar setConfig({ ...config, layout: event.layout }) + // O DashKit mantém o estado visual internamente + }); + + return unsubscribe; + }, []); + + return {}} />; +} +``` + +**Importante:** Se você atualizar posteriormente `config.layout` a partir das props (por exemplo, de uma sincronização do servidor), o DashKit redefinirá sua linha de base interna para corresponder à nova prop. Isso garante a compatibilidade com fluxos de trabalho orientados a eventos e controlados. + ### Menu -Você pode especificar um menu de sobreposição personalizado para widgets do DashKit no modo de edição. +Você pode especificar um menu de sobreposição de widget DashKit personalizado no modo de edição ```ts type MenuItem = { @@ -378,7 +452,7 @@ type MenuItem = { title?: string; // título em string icon?: ReactNode; // nó do ícone iconSize?: number | string; // tamanho do ícone em px como número ou como string com unidades - handler?: (item: ConfigItem) => void; // manipulador de ação personalizado do item + handler?: (item: ConfigItem) => void; // manipulador de ação de item personalizado visible?: (item: ConfigItem) => boolean; // manipulador de visibilidade opcional para filtrar itens do menu className?: string; // propriedade de classe personalizada }; @@ -386,7 +460,7 @@ type MenuItem = { // use um array de itens de menu nas configurações | null} /> -[obsoleto] +[depreciado] // a propriedade overlayMenuItems tem prioridade maior sobre o menu setSettings DashKit.setSettings({menu: [] as Array}); ``` @@ -408,35 +482,38 @@ interface DashKitDnDWrapperProps { dragImageSrc?: string; onDragStart?: (dragProps: ItemDragProps) => void; onDragEnd?: () => void; - onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) => void | boolean; + onDropDragOver?: ( + draggedItem: DraggedOverItem, + sharedItem: DraggedOverItem | null, + ) => void | boolean; } ``` -- **dragImageSrc**: Prévia da imagem de arrastar, por padrão é usado um png transparente de 1px em base64. -- **onDragStart**: Callback chamado quando um elemento é arrastado do ActionPanel. -- **onDragEnd**: Callback chamado quando um elemento é solto ou o arrasto é cancelado. +- **dragImageSrc**: Prévia da imagem de arrastar, por padrão é usado um png transparente de 1px em base64 +- **onDragStart**: Callback chamado quando um elemento é arrastado do ActionPanel +- **onDragEnd**: Callback chamado quando o elemento é solto ou o arrasto é cancelado ```ts type ItemDragProps = { - type: string; // Tipo do plugin - layout?: { // Opcional. Tamanho do item do layout para pré-visualização e inicialização - w?: number; - h?: number; - }; - extra?: any; // Contexto customizado do usuário + type: string; // Tipo de plugin + layout?: { + // Opcional. Tamanho do item de layout para prévia e inicialização + w?: number; + h?: number; + }; + extra?: any; // Contexto personalizado do usuário }; ``` ```ts type ItemDropProps = { - commit: () => void; // O callback deve ser chamado após todas as operações de configuração serem feitas - dragProps: ItemDragProps; // Props de arrastar do item - itemLayout: ConfigLayout; // Dimensões calculadas do layout do item - newLayout: ConfigLayout[]; // Novo layout após o elemento ser solto + commit: () => void; // Callback deve ser chamado após todas as operações de configuração serem feitas + dragProps: ItemDragProps; // Props de arrastar do item + itemLayout: ConfigLayout; // Dimensões calculadas do item de layout + newLayout: ConfigLayout[]; // Novo layout após o elemento ser solto }; ``` - #### Exemplo: ```jsx @@ -466,26 +543,26 @@ const onDrop = (dropProps: ItemDropProps) => { ### API CSS | Nome | Descrição | -| :--------------------------------------------- | :-------------------- | -| Variáveis do painel de ação | | -| `--dashkit-action-panel-color` | Cor de fundo | -| `--dashkit-action-panel-border-color` | Cor da borda | -| `--dashkit-action-panel-border-radius` | Raio da borda | -| Variáveis do item do painel de ação | | -| `--dashkit-action-panel-item-color` | Cor de fundo | -| `--dashkit-action-panel-item-text-color` | Cor do texto | +| :--------------------------------------------- | :------------------ | +| Variáveis do painel de ação | | +| `--dashkit-action-panel-color` | Cor de fundo | +| `--dashkit-action-panel-border-color` | Cor da borda | +| `--dashkit-action-panel-border-radius` | Raio da borda | +| Variáveis do item do painel de ação | | +| `--dashkit-action-panel-item-color` | Cor de fundo | +| `--dashkit-action-panel-item-text-color` | Cor do texto | | `--dashkit-action-panel-item-color-hover` | Cor de fundo ao passar o mouse | -| `--dashkit-action-panel-item-text-color-hover` | Cor do texto ao passar o mouse | -| Variáveis da sobreposição | | -| `--dashkit-overlay-border-color` | Cor da borda | -| `--dashkit-overlay-color` | Cor de fundo | -| `--dashkit-overlay-opacity` | Opacidade | -| Variáveis do item da grade | | -| `--dashkit-grid-item-edit-opacity` | Opacidade | -| `--dashkit-grid-item-border-radius` | Raio da borda | -| Variáveis do placeholder | | -| `--dashkit-placeholder-color` | Cor de fundo | -| `--dashkit-placeholder-opacity` | Opacidade | +| `--dashkit-action-panel-item-text-color-hover` | Cor do texto ao passar o mouse | +| Variáveis de sobreposição | | +| `--dashkit-overlay-border-color` | Cor da borda | +| `--dashkit-overlay-color` | Cor de fundo | +| `--dashkit-overlay-opacity` | Opacidade | +| Variáveis do item da grade | | +| `--dashkit-grid-item-edit-opacity` | Opacidade | +| `--dashkit-grid-item-border-radius` | Raio da borda | +| Variáveis do placeholder | | +| `--dashkit-placeholder-color` | Cor de fundo | +| `--dashkit-placeholder-opacity` | Opacidade | #### Exemplo de uso @@ -520,17 +597,16 @@ const CustomThemeWrapper = (props: { ## Desenvolvimento -### Build e watch +### Compilar e observar -- Construir dependências `npm ci` -- Construir o projeto `npm run build` -- Construir o storybook `npm run start` +- Instalar dependências `npm ci` +- Compilar o projeto `npm run build` +- Compilar o storybook `npm run start` Por padrão, o storybook roda em `http://localhost:7120/`. -Novas alterações no projeto nem sempre são capturadas quando o storybook está em execução, então é melhor reconstruir o projeto manualmente e reiniciar o storybook. - +Novas alterações no projeto nem sempre são refletidas quando o storybook está rodando, então é melhor recompilar o projeto manualmente e reiniciar o storybook. -### Exemplo de configuração nginx para desenvolvimento em uma máquina de desenvolvimento +### Exemplo de configuração do nginx para desenvolvimento em uma máquina de desenvolvimento ```bash server { diff --git a/src/content/local-docs/libs/dashkit/README-zh.md b/src/content/local-docs/libs/dashkit/README-zh.md index 851602b06c04..e5fb318ecbe3 100644 --- a/src/content/local-docs/libs/dashkit/README-zh.md +++ b/src/content/local-docs/libs/dashkit/README-zh.md @@ -25,12 +25,12 @@ npm i @gravity-ui/dashkit @gravity-ui/uikit ```ts type ItemManipulationCallback = (eventData: { - layout: Layout[]; - oldItem: Layout; - newItem: Layout; - placeholder: Layout; - e: MouseEvent; - element: HTMLElement; + layout: Layout[]; + oldItem: Layout; + newItem: Layout; + placeholder: Layout; + e: MouseEvent; + element: HTMLElement; }) => void; interface DashKitProps { @@ -75,10 +75,10 @@ interface DashKitProps { - **onDrop**: 使用 (#DashKitDnDWrapper) 从 ActionPanel 拖放项目时调用 - **onItemMountChange**: 项目挂载状态更改时调用 - **onItemRender**: 项目渲染完成时调用 -- **defaultGlobalParams**, **globalParams**: 影响所有小部件的 [参数](#Params)。在 DataLens 中,`defaultGlobalParams` 是在仪表盘设置中设置的全局参数。`globalParams` 是可以在 URL 中设置的全局参数。 +- **defaultGlobalParams**, **globalParams**: 影响所有小部件的[参数](#Params)。在 DataLens 中,`defaultGlobalParams` 是在仪表盘设置中设置的全局参数。`globalParams` 是可以在 URL 中设置的全局参数。 - **itemsStateAndParams**: [itemsStateAndParams](#itemsStateAndParams)。 - **settings**: DashKit 设置。 -- **context**: 将会传递给所有小部件的对象。 +- **context**: 将被传递给所有小部件的对象。 - **overlayControls**: 在编辑时覆盖小部件控件的对象。如果未传递,将显示基本控件。如果传递 `null`,则仅显示关闭按钮或自定义菜单。 - **overlayMenuItems**: 自定义下拉菜单项 - **noOverlay**: 如果为 `true`,则在编辑时不会显示覆盖层和控件。 @@ -92,8 +92,8 @@ interface DashKitProps { - **onResizeStart**: ReactGridLayout 在项目调整大小开始时调用 - **onResize**: ReactGridLayout 在项目调整大小时调用 - **onResizeStop**: ReactGridLayout 在项目调整大小停止时调用 -- **getPreparedCopyItemOptions**: 在保存到本地存储之前,用于将复制的项目转换为可序列化对象。它应该取代已弃用的 `context.getPreparedCopyItemOptions` prop -- **onCopyFulfill**: 在项目复制成功完成时调用,此时 `error=null` 且 `data` 已定义;否则,将调用 `error: Error` 而不带 `data` +- **getPreparedCopyItemOptions**: 在保存到本地存储之前,用于将复制的项目转换为可序列化对象时调用。它应该替代已弃用的 `context.getPreparedCopyItemOptions` prop +- **onCopyFulfill**: 在项目复制成功完成时(`error=null` 且 `data` 已定义)调用,否则以 `error: Error` 而不带 `data` 调用 ## 用法 @@ -152,7 +152,7 @@ interface DashKitProps { }); ``` -### 配置 +### Config ```ts export interface Config { @@ -165,7 +165,7 @@ export interface Config { } ``` -配置示例: +Config 示例: ```ts import {DashKitProps} from '@gravity-ui/dashkit'; @@ -180,7 +180,7 @@ const config: DashKitProps['config'] = { id: 'tT', data: { size: 'm', - text: '标题', + text: 'Caption', showInTOC: true, }, type: 'title', @@ -190,7 +190,7 @@ const config: DashKitProps['config'] = { { id: 'Ea', data: { - text: '模式 _editActive', + text: 'mode _editActive', _editActive: true, }, type: 'text', @@ -199,7 +199,7 @@ const config: DashKitProps['config'] = { { id: 'zR', data: { - text: '### 文本', + text: '### Text', }, type: 'text', namespace: 'default', @@ -273,7 +273,7 @@ const newLayout = updateLayout: [ const newConfig = DashKit.setItem({ item: { data: { - text: `一些文本`, + text: `Some text`, }, namespace: 'default', type: 'text', @@ -293,7 +293,7 @@ const newConfig = DashKit.setItem({ }); ``` -更改现有项: +更改配置中的现有项: ```ts const newConfig = DashKit.setItem({ @@ -301,7 +301,7 @@ const newConfig = DashKit.setItem({ id: 'tT', // item.id data: { size: 'm', - text: `新的标题`, + text: `New caption`, }, namespace: 'default', type: 'title', @@ -310,7 +310,7 @@ const newConfig = DashKit.setItem({ }); ``` -删除一项: +从配置中删除一项: ```ts import {DashKitProps} from '@gravity-ui/dashkit'; @@ -324,7 +324,7 @@ const {config: newConfig, itemsStateAndParams} = DashKit.removeItem({ }); ``` -### 参数 +### Params ```ts type Params = Record; @@ -368,17 +368,91 @@ interface ItemsStateAndParamsBase { type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase; ``` +### 实验性 DashKit 事件 + +> 实验性:此 API 可能会在次要版本中发生更改。 + +`DashKit` 公开了一个实验性的实例事件 API。使用组件 ref 并通过 `dashkitRef.current?.on(eventName, handler)` 进行订阅。该方法返回一个取消订阅的回调函数。 + +支持的第一个事件是 `change`。当布局发生更改时会发出此事件,在调用 `onChange` 之前。处理程序可以读取完整的下一个和上一个布局,读取布局补丁,或调用 `preventDefault()` 来阻止默认的 `onChange` 调用。 + +```tsx +import React from 'react'; +import {DashKit} from '@gravity-ui/dashkit'; +import type {DashKitChangeEvent} from '@gravity-ui/dashkit'; + +function Dashboard() { + const dashkitRef = React.useRef(null); + + React.useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event: DashKitChangeEvent) => { + console.log(event.patches); + + if (event.patches.length > 0) { + event.preventDefault(); + } + }); + + return () => unsubscribe?.(); + }, []); + + return ; +} +``` + +```ts +type DashKitLayoutPatch = Pick & + Partial>; + +type DashKitChangeEvent = { + patches: DashKitLayoutPatch[]; + layout: ConfigLayout[]; + previousLayout: ConfigLayout[]; + preventDefault: () => void; + readonly defaultPrevented: boolean; +}; +``` + +#### 事件驱动的布局更新 + +如果您在 `change` 事件处理程序中使用了 `preventDefault()`,现在您可以处理布局更新而无需重新初始化 `config` prop。DashKit 会维护一个内部基线并逐步计算补丁: + +```tsx +function Dashboard() { + const [config, setConfig] = useState(initialConfig); + const dashkitRef = useRef(null); + + useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event) => { + event.preventDefault(); // 不调用 onChange + + // 只将增量补丁发送到您的后端 + sendPatches(event.patches); + + // 无需调用 setConfig({ ...config, layout: event.layout }) + // DashKit 会在内部维护视觉状态 + }); + + return unsubscribe; + }, []); + + return {}} />; +} +``` + +**重要提示:** 如果您之后从 props 更新 `config.layout`(例如,从服务器同步),DashKit 会重置其内部基线以匹配新的 prop。这确保了与事件驱动和受控工作流的兼容性。 + ### 菜单 -在编辑模式下,您可以为 DashKit 小部件指定自定义覆盖菜单。 +您可以在编辑模式下为 DashKit 指定自定义的 widget 覆盖菜单。 ```ts type MenuItem = { id: string; // 唯一 ID title?: string; // 字符串标题 icon?: ReactNode; // 图标节点 - iconSize?: number | string; // 图标大小,以像素为单位(数字)或带单位的字符串 - handler?: (item: ConfigItem) => void; // 自定义项操作处理程序 + iconSize?: number | string; // 图标大小,以 px 为单位的数字或带单位的字符串 + handler?: (item: ConfigItem) => void; // 自定义菜单项操作处理程序 visible?: (item: ConfigItem) => boolean; // 用于过滤菜单项的可选可见性处理程序 className?: string; // 自定义类属性 }; @@ -387,11 +461,11 @@ type MenuItem = { | null} /> [已弃用] -// overlayMenuItems 属性的优先级高于 setSettings 菜单 +// overlayMenuItems 属性的优先级高于 setSettings 的 menu DashKit.setSettings({menu: [] as Array}); ``` -### 从 ActionPanel 拖动的项 +### 从 ActionPanel 拖拽项目 #### DashKitDnDWrapper @@ -405,38 +479,41 @@ type DraggedOverItem = { }; interface DashKitDnDWrapperProps { - dragImageSrc?: string; // 拖动图像预览,默认使用透明的 1px png base64 - onDragStart?: (dragProps: ItemDragProps) => void; // 当元素从 ActionPanel 拖动时调用的回调 - onDragEnd?: () => void; // 当元素被放置或拖动取消时调用的回调 - onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) => void | boolean; // 当元素被放置在目标上时调用的回调 + dragImageSrc?: string; // 拖拽图像预览,默认使用透明的 1px png base64 + onDragStart?: (dragProps: ItemDragProps) => void; // 当元素从 ActionPanel 拖拽时调用的回调 + onDragEnd?: () => void; // 当元素被放置或拖拽取消时调用的回调 + onDropDragOver?: ( + draggedItem: DraggedOverItem, + sharedItem: DraggedOverItem | null, + ) => void | boolean; } ``` -- **dragImageSrc**: 拖动图像预览,默认使用透明的 1px png base64。 -- **onDragStart**: 当元素从 ActionPanel 拖动时调用的回调。 -- **onDragEnd**: 当元素被放置或拖动取消时调用的回调。 +- **dragImageSrc**: 拖拽图像预览,默认使用透明的 1px png base64。 +- **onDragStart**: 当元素从 ActionPanel 拖拽时调用的回调。 +- **onDragEnd**: 当元素被放置或拖拽取消时调用的回调。 ```ts type ItemDragProps = { - type: string; // 插件类型 - layout?: { // 可选。用于预览和初始化的布局项大小 - w?: number; - h?: number; - }; - extra?: any; // 自定义用户上下文 + type: string; // 插件类型 + layout?: { + // 可选。用于预览和初始化的布局项大小 + w?: number; + h?: number; + }; + extra?: any; // 自定义用户上下文 }; ``` ```ts type ItemDropProps = { - commit: () => void; // 在所有配置操作完成后应调用此回调 - dragProps: ItemDragProps; // 项拖拽属性 - itemLayout: ConfigLayout; // 计算出的项布局尺寸 - newLayout: ConfigLayout[]; // 元素放置后的新布局 + commit: () => void; // 在所有配置操作完成后应调用的回调 + dragProps: ItemDragProps; // 项目拖拽属性 + itemLayout: ConfigLayout; // 计算出的项目布局尺寸 + newLayout: ConfigLayout[]; // 元素被放置后的新布局 }; ``` - #### 示例: ```jsx @@ -467,25 +544,25 @@ const onDrop = (dropProps: ItemDropProps) => { | 名称 | 描述 | | :--------------------------------------------- | :------------- | -| 操作面板变量 | | +| Action panel 变量 | | | `--dashkit-action-panel-color` | 背景颜色 | | `--dashkit-action-panel-border-color` | 边框颜色 | | `--dashkit-action-panel-border-radius` | 边框圆角 | -| 操作面板项变量 | | +| Action panel item 变量 | | | `--dashkit-action-panel-item-color` | 背景颜色 | | `--dashkit-action-panel-item-text-color` | 文本颜色 | -| `--dashkit-action-panel-item-color-hover` | 悬停背景颜色 | -| `--dashkit-action-panel-item-text-color-hover` | 悬停文本颜色 | -| 覆盖层变量 | | +| `--dashkit-action-panel-item-color-hover` | 鼠标悬停时的背景颜色 | +| `--dashkit-action-panel-item-text-color-hover` | 鼠标悬停时的文本颜色 | +| Overlay 变量 | | | `--dashkit-overlay-border-color` | 边框颜色 | | `--dashkit-overlay-color` | 背景颜色 | -| `--dashkit-overlay-opacity` | 透明度 | -| 网格项变量 | | -| `--dashkit-grid-item-edit-opacity` | 透明度 | +| `--dashkit-overlay-opacity` | 不透明度 | +| Grid item 变量 | | +| `--dashkit-grid-item-edit-opacity` | 不透明度 | | `--dashkit-grid-item-border-radius` | 边框圆角 | -| 占位符变量 | | +| Placeholder 变量 | | | `--dashkit-placeholder-color` | 背景颜色 | -| `--dashkit-placeholder-opacity` | 透明度 | +| `--dashkit-placeholder-opacity` | 不透明度 | #### 使用示例 @@ -522,15 +599,14 @@ const CustomThemeWrapper = (props: { ### 构建与监听 -- 构建依赖 `npm ci` +- 安装依赖 `npm ci` - 构建项目 `npm run build` -- 构建 storybook `npm run start` - -默认情况下,storybook 运行在 `http://localhost:7120/`。 -当 storybook 运行时,项目中的新更改并非总能被捕获,因此最好手动重新构建项目并重启 storybook。 +- 构建 Storybook `npm run start` +默认情况下,Storybook 运行在 `http://localhost:7120/`。 +当 Storybook 运行时,项目中的新更改不一定会被立即捕获,因此最好手动重新构建项目并重启 Storybook。 -### 开发机器上 nginx 配置示例 +### 开发环境下 Nginx 配置示例 ```bash server { diff --git a/src/content/local-docs/libs/dashkit/README.md b/src/content/local-docs/libs/dashkit/README.md index c1b844a713bc..9660a2eaa9ea 100644 --- a/src/content/local-docs/libs/dashkit/README.md +++ b/src/content/local-docs/libs/dashkit/README.md @@ -25,12 +25,12 @@ Plugins are required to create custom widgets. ```ts type ItemManipulationCallback = (eventData: { - layout: Layout[]; - oldItem: Layout; - newItem: Layout; - placeholder: Layout; - e: MouseEvent; - element: HTMLElement; + layout: Layout[]; + oldItem: Layout; + newItem: Layout; + placeholder: Layout; + e: MouseEvent; + element: HTMLElement; }) => void; interface DashKitProps { @@ -366,6 +366,80 @@ interface ItemsStateAndParamsBase { type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase; ``` +### Experimental DashKit events + +> Experimental: this API can change in minor releases. + +`DashKit` exposes an experimental instance event API. Use a component ref and subscribe with `dashkitRef.current?.on(eventName, handler)`. The method returns an unsubscribe callback. + +The first supported event is `change`. It is emitted when the layout changes, before `onChange` is called. The handler can read the full next and previous layouts, read layout patches, or call `preventDefault()` to stop the default `onChange` call. + +```tsx +import React from 'react'; +import {DashKit} from '@gravity-ui/dashkit'; +import type {DashKitChangeEvent} from '@gravity-ui/dashkit'; + +function Dashboard() { + const dashkitRef = React.useRef(null); + + React.useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event: DashKitChangeEvent) => { + console.log(event.patches); + + if (event.patches.length > 0) { + event.preventDefault(); + } + }); + + return () => unsubscribe?.(); + }, []); + + return ; +} +``` + +```ts +type DashKitLayoutPatch = Pick & + Partial>; + +type DashKitChangeEvent = { + patches: DashKitLayoutPatch[]; + layout: ConfigLayout[]; + previousLayout: ConfigLayout[]; + preventDefault: () => void; + readonly defaultPrevented: boolean; +}; +``` + +#### Event-driven layout updates + +If you use `preventDefault()` in the `change` event handler, you can now handle layout updates without re-initializing the config prop. DashKit maintains an internal baseline and computes patches incrementally: + +```tsx +function Dashboard() { + const [config, setConfig] = useState(initialConfig); + const dashkitRef = useRef(null); + + useEffect(() => { + const unsubscribe = dashkitRef.current?.on('change', (event) => { + event.preventDefault(); // Don't call onChange + + // Send only the incremental patches to your backend + sendPatches(event.patches); + + // No need to call setConfig({ ...config, layout: event.layout }) + // DashKit maintains the visual state internally + }); + + return unsubscribe; + }, []); + + return {}} />; +} +``` + +**Important:** If you later update `config.layout` from props (e.g., from server sync), DashKit will reset its internal baseline to match the new prop. This ensures compatibility with both event-driven and controlled workflows. + ### Menu You can specify custom DashKit widget overlay menu in edit mode @@ -406,7 +480,10 @@ interface DashKitDnDWrapperProps { dragImageSrc?: string; onDragStart?: (dragProps: ItemDragProps) => void; onDragEnd?: () => void; - onDropDragOver?: (draggedItem: DraggedOverItem, sharedItem: DraggedOverItem | null) => void | boolean; + onDropDragOver?: ( + draggedItem: DraggedOverItem, + sharedItem: DraggedOverItem | null, + ) => void | boolean; } ``` @@ -416,25 +493,25 @@ interface DashKitDnDWrapperProps { ```ts type ItemDragProps = { - type: string; // Plugin type - layout?: { // Optional. Layout item size for preview and init - w?: number; - h?: number; - }; - extra?: any; // Custom user context + type: string; // Plugin type + layout?: { + // Optional. Layout item size for preview and init + w?: number; + h?: number; + }; + extra?: any; // Custom user context }; ``` ```ts type ItemDropProps = { - commit: () => void; // Callback should be called after all config operations are made - dragProps: ItemDragProps; // Item drag props - itemLayout: ConfigLayout; // Calculated item layout dimensions - newLayout: ConfigLayout[]; // New layout after element is dropped + commit: () => void; // Callback should be called after all config operations are made + dragProps: ItemDragProps; // Item drag props + itemLayout: ConfigLayout; // Calculated item layout dimensions + newLayout: ConfigLayout[]; // New layout after element is dropped }; ``` - #### Example: ```jsx @@ -527,7 +604,6 @@ const CustomThemeWrapper = (props: { By default, storybook runs on `http://localhost:7120/`. New changes from a project aren't always picked up when storybook is running, so it's better to rebuild a project manually and restart storybook. - ### Example of an nginx config for development on a dev machine ```bash