@ichicraft/widgets-widget-base 1.20.0 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +619 -463
- package/lib/dev/createWidgetDevServerConfig.js +3 -3
- package/lib/dev/findAvailablePort.js +3 -4
- package/lib/types/index.d.ts +138 -1
- package/lib/types/index.js +33 -1
- package/lib/utils/ConfigurationHelper.d.ts +3 -3
- package/lib/utils/ConfigurationHelper.js +2 -2
- package/package.json +14 -18
|
@@ -12,7 +12,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.
|
|
15
|
+
exports.DEFAULT_WIDGET_DEBUG_PORT = void 0;
|
|
16
|
+
exports.createWidgetDevServerConfig = createWidgetDevServerConfig;
|
|
16
17
|
const fs_1 = __importDefault(require("fs"));
|
|
17
18
|
const os_1 = __importDefault(require("os"));
|
|
18
19
|
const path_1 = __importDefault(require("path"));
|
|
@@ -27,8 +28,8 @@ exports.DEFAULT_WIDGET_DEBUG_PORT = 8080;
|
|
|
27
28
|
* board always matches the port the server actually binds to.
|
|
28
29
|
*/
|
|
29
30
|
function createWidgetDevServerConfig(options) {
|
|
30
|
-
var _a;
|
|
31
31
|
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
+
var _a;
|
|
32
33
|
const { projectPath, serveConfig } = options;
|
|
33
34
|
const port = (_a = serveConfig.debugPort) !== null && _a !== void 0 ? _a : (yield (0, findAvailablePort_1.findAvailablePort)(exports.DEFAULT_WIDGET_DEBUG_PORT));
|
|
34
35
|
const manifestUrl = `https://localhost:${port}/manifest.json`;
|
|
@@ -74,7 +75,6 @@ function createWidgetDevServerConfig(options) {
|
|
|
74
75
|
};
|
|
75
76
|
});
|
|
76
77
|
}
|
|
77
|
-
exports.createWidgetDevServerConfig = createWidgetDevServerConfig;
|
|
78
78
|
/**
|
|
79
79
|
* Uses the SPFx localhost certificate that was trusted with `gulp trust-dev-cert`,
|
|
80
80
|
* falling back to the rushstack certificate on newer toolchains.
|
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.findAvailablePort =
|
|
15
|
+
exports.findAvailablePort = findAvailablePort;
|
|
16
16
|
const net_1 = __importDefault(require("net"));
|
|
17
17
|
/** Both loopback stacks are checked: a dev server on one of them still owns the port. */
|
|
18
18
|
const LOOPBACK_HOSTS = ['127.0.0.1', '::1'];
|
|
@@ -20,8 +20,8 @@ const LOOPBACK_HOSTS = ['127.0.0.1', '::1'];
|
|
|
20
20
|
* Resolves the first free TCP port at or above `startPort`, so several widget dev servers
|
|
21
21
|
* can run side by side without anyone having to hand out port numbers.
|
|
22
22
|
*/
|
|
23
|
-
function findAvailablePort(
|
|
24
|
-
return __awaiter(this,
|
|
23
|
+
function findAvailablePort(startPort_1) {
|
|
24
|
+
return __awaiter(this, arguments, void 0, function* (startPort, attempts = 50) {
|
|
25
25
|
for (let port = startPort; port < startPort + attempts; port++) {
|
|
26
26
|
if (yield isPortAvailable(port)) {
|
|
27
27
|
return port;
|
|
@@ -30,7 +30,6 @@ function findAvailablePort(startPort, attempts = 50) {
|
|
|
30
30
|
throw new Error(`[widgets-widget-base] No free port found between ${startPort} and ${startPort + attempts - 1}. Stop a running dev server or set "debugPort" in config/serve.config.ts.`);
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
-
exports.findAvailablePort = findAvailablePort;
|
|
34
33
|
function isPortAvailable(port) {
|
|
35
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
36
35
|
for (const host of LOOPBACK_HOSTS) {
|
package/lib/types/index.d.ts
CHANGED
|
@@ -345,14 +345,28 @@ export interface WidgetInstanceContext {
|
|
|
345
345
|
* Functionality offered by the widget board to append the title of the widget with additional text.
|
|
346
346
|
*/
|
|
347
347
|
setWidgetTitleSuffix?: (suffix: string) => void;
|
|
348
|
+
/**
|
|
349
|
+
* Displays a badge after the title of the widget. A number is displayed as a count badge, a string as its text.
|
|
350
|
+
* Provide `undefined`, `0` or an empty string to remove the badge.
|
|
351
|
+
*/
|
|
352
|
+
setWidgetTitleBadge?: (badge: string | number | undefined) => void;
|
|
353
|
+
/**
|
|
354
|
+
* Displays an icon before the title of the widget. Provide `undefined` to remove the icon.
|
|
355
|
+
*/
|
|
356
|
+
setWidgetHeaderIcon?: (icon: WidgetHeaderIconProps | undefined) => void;
|
|
348
357
|
/**
|
|
349
358
|
* Functionality offered by the widget board to change the subtitle of the widget.
|
|
350
359
|
*/
|
|
351
360
|
setWidgetSubtitle?: (subtitle: string) => void;
|
|
352
361
|
/**
|
|
353
362
|
* Show or hide the header of the widget, allowing widgets to take control of full widget real estate.
|
|
363
|
+
* @deprecated Use `setWidgetRenderOptions` instead. `true` maps to `WidgetHeaderRenderMode.Default`, `false` to `WidgetHeaderRenderMode.Overlay`.
|
|
354
364
|
*/
|
|
355
365
|
setWidgetHeaderVisibility?: (visible: boolean) => void;
|
|
366
|
+
/**
|
|
367
|
+
* Changes how the widget board renders the chrome around this widget. Only the provided options are changed.
|
|
368
|
+
*/
|
|
369
|
+
setWidgetRenderOptions?: (options: Partial<WidgetRenderOptions>) => void;
|
|
356
370
|
/**
|
|
357
371
|
* Show or hide the settings button of the widget.
|
|
358
372
|
*/
|
|
@@ -410,6 +424,123 @@ export interface WidgetInstanceContext {
|
|
|
410
424
|
* Data stored here is specific to this instance only.
|
|
411
425
|
*/
|
|
412
426
|
cache: CacheManager;
|
|
427
|
+
/**
|
|
428
|
+
* Properties of this widget instance that can change while the widget is loaded, such as the size it occupies in the board grid.
|
|
429
|
+
* Subscribe to be notified of changes without the widget being reloaded.
|
|
430
|
+
*/
|
|
431
|
+
dynamic?: DynamicWidgetInstanceContext;
|
|
432
|
+
}
|
|
433
|
+
export declare enum WidgetHeaderRenderMode {
|
|
434
|
+
/** A header bar at the top of the widget, showing the title and actions. */
|
|
435
|
+
Default = "default",
|
|
436
|
+
/** No header bar. Actions are shown on top of the widget body when hovering the widget. */
|
|
437
|
+
Overlay = "overlay"
|
|
438
|
+
}
|
|
439
|
+
export declare enum WidgetHeaderActionsMode {
|
|
440
|
+
/** All actions available to the user. */
|
|
441
|
+
All = "all",
|
|
442
|
+
/** Only essential actions the user can currently perform; informational, secondary and disabled actions are hidden. */
|
|
443
|
+
Limited = "limited"
|
|
444
|
+
}
|
|
445
|
+
export declare enum WidgetBodyRenderMode {
|
|
446
|
+
/** The widget is rendered on a card, with a background and shadow. */
|
|
447
|
+
Default = "default",
|
|
448
|
+
/** No background or shadow. The header is always rendered as `WidgetHeaderRenderMode.Overlay`. */
|
|
449
|
+
Transparent = "transparent"
|
|
450
|
+
}
|
|
451
|
+
export interface WidgetHeaderIconProps {
|
|
452
|
+
/** Name of a Fluent UI icon. */
|
|
453
|
+
iconName?: string;
|
|
454
|
+
/** Url of an image, used when no `iconName` is provided. */
|
|
455
|
+
imageUrl?: string;
|
|
456
|
+
/** Color of the icon. Only applies to `iconName`. Defaults to the theme's primary color. */
|
|
457
|
+
color?: string;
|
|
458
|
+
/** Tooltip displayed when hovering the icon. */
|
|
459
|
+
tooltip?: string;
|
|
460
|
+
}
|
|
461
|
+
export interface WidgetRenderOptions {
|
|
462
|
+
/** How the header is rendered. Defaults to `WidgetHeaderRenderMode.Default`. */
|
|
463
|
+
headerMode: WidgetHeaderRenderMode;
|
|
464
|
+
/** Which actions the header offers. Defaults to `WidgetHeaderActionsMode.All`. */
|
|
465
|
+
actionsMode: WidgetHeaderActionsMode;
|
|
466
|
+
/** How the widget body is rendered. Defaults to `WidgetBodyRenderMode.Default`. */
|
|
467
|
+
bodyMode: WidgetBodyRenderMode;
|
|
468
|
+
}
|
|
469
|
+
export declare enum WidgetUserConfigAccess {
|
|
470
|
+
/** The widget has no user configuration (`isConfigurableByUser` is `false` in its manifest). */
|
|
471
|
+
None = "none",
|
|
472
|
+
/** The current user can change this widget's user configuration. */
|
|
473
|
+
Editable = "editable",
|
|
474
|
+
/** The current user normally can, but not right now, e.g. while another user edits the shared board or the SharePoint page is in edit mode. */
|
|
475
|
+
Blocked = "blocked",
|
|
476
|
+
/** The current user can't change this widget's user configuration, e.g. when viewing someone else's shared board. */
|
|
477
|
+
ReadOnly = "readOnly"
|
|
478
|
+
}
|
|
479
|
+
export interface WidgetGridItemSize {
|
|
480
|
+
/** Number of board grid columns the widget occupies. */
|
|
481
|
+
columns: number;
|
|
482
|
+
/** Number of board grid rows the widget occupies. */
|
|
483
|
+
rows: number;
|
|
484
|
+
}
|
|
485
|
+
/** Widget properties that can change while the widget is loaded. */
|
|
486
|
+
export interface DynamicWidgetInstanceContextValue {
|
|
487
|
+
/**
|
|
488
|
+
* The widget's current title: set through `setWidgetTitle`, renamed by the user, or the variant's title, in that order.
|
|
489
|
+
* Excludes the suffix set through `setWidgetTitleSuffix`.
|
|
490
|
+
*/
|
|
491
|
+
title?: string;
|
|
492
|
+
/** The widget's current subtitle: set through `setWidgetSubtitle` or the variant's subtitle, with its tokens replaced. */
|
|
493
|
+
subtitle?: string;
|
|
494
|
+
/** The tab shown as selected, whether the widget or the user selected it. */
|
|
495
|
+
selectedTabId?: string;
|
|
496
|
+
/** This instance's deep link data in the current url; the same value `getDeepLinkData()` returns. */
|
|
497
|
+
deepLinkData: string;
|
|
498
|
+
/** The size the widget occupies in the board grid. Only set when the widget is on a board, not in the buddy bar or a web part. */
|
|
499
|
+
size?: WidgetGridItemSize;
|
|
500
|
+
/**
|
|
501
|
+
* The render options the widget board currently applies: the options requested through `setWidgetRenderOptions`,
|
|
502
|
+
* after the board's overrides. For example, the header renders as an overlay when the widget
|
|
503
|
+
* is scaled down, and the body keeps its card while an error is shown.
|
|
504
|
+
*/
|
|
505
|
+
renderOptions: WidgetRenderOptions;
|
|
506
|
+
/** Whether the user is dragging the widget. */
|
|
507
|
+
isDragging: boolean;
|
|
508
|
+
/** Whether the user is resizing the widget. While `true`, `size` describes the size the widget will snap to. */
|
|
509
|
+
isResizing: boolean;
|
|
510
|
+
/** Pointer events on the widget body are blocked, e.g. while any widget on the board is dragged or resized. */
|
|
511
|
+
isPointerEventsDisabled: boolean;
|
|
512
|
+
/** Whether the current user can change this widget's user configuration right now. */
|
|
513
|
+
userConfigAccess: WidgetUserConfigAccess;
|
|
514
|
+
/**
|
|
515
|
+
* The design settings of the user's current theme; the live counterpart of `WidgetContext.design`.
|
|
516
|
+
* The widget is reloaded when this changes, unless it subscribed to `design` by name.
|
|
517
|
+
*/
|
|
518
|
+
design: WidgetDesignContext;
|
|
519
|
+
/**
|
|
520
|
+
* The currently used theme, e.g. after switching to dark mode; the live counterpart of `WidgetContext.theme`.
|
|
521
|
+
* The widget is reloaded when this changes, unless it subscribed to `theme` by name.
|
|
522
|
+
*/
|
|
523
|
+
theme: any;
|
|
524
|
+
}
|
|
525
|
+
export type DynamicWidgetInstanceContextKey = keyof DynamicWidgetInstanceContextValue;
|
|
526
|
+
export type DynamicWidgetInstanceContextListener = (value: DynamicWidgetInstanceContextValue) => void;
|
|
527
|
+
export interface DynamicWidgetInstanceContext {
|
|
528
|
+
/** The current value. Also available during `init` and `render`. */
|
|
529
|
+
readonly current: DynamicWidgetInstanceContextValue;
|
|
530
|
+
/**
|
|
531
|
+
* Calls the listener when one of `keys` changes, or on every change when `keys` is omitted.
|
|
532
|
+
* Subscribing to `design` or `theme` by name tells the widget board the widget applies those changes itself,
|
|
533
|
+
* so it isn't reloaded when they change. Subscribing the same listener again replaces its keys.
|
|
534
|
+
* @returns A function that removes this listener.
|
|
535
|
+
*/
|
|
536
|
+
subscribe: (listener: DynamicWidgetInstanceContextListener, keys?: DynamicWidgetInstanceContextKey[]) => () => void;
|
|
537
|
+
/** Removes a listener passed to `subscribe`. Requires the same function reference. */
|
|
538
|
+
unsubscribe: (listener: DynamicWidgetInstanceContextListener) => void;
|
|
539
|
+
/**
|
|
540
|
+
* Removes all listeners of this widget, including those added by hooks of mounted components.
|
|
541
|
+
* Intended for teardown, e.g. in `cleanupResources`.
|
|
542
|
+
*/
|
|
543
|
+
unsubscribeAll: () => void;
|
|
413
544
|
}
|
|
414
545
|
export interface WidgetBuddyContext {
|
|
415
546
|
/**
|
|
@@ -491,14 +622,20 @@ export interface WidgetManifestContext {
|
|
|
491
622
|
* Data stored here is shared across all variants and instances of this widget type.
|
|
492
623
|
*/
|
|
493
624
|
cache: CacheManager;
|
|
625
|
+
/**
|
|
626
|
+
* Whether the widget board loaded this widget from a local debug session instead of its published build.
|
|
627
|
+
*/
|
|
628
|
+
isDebugging?: boolean;
|
|
494
629
|
}
|
|
495
630
|
export interface WidgetDesignContext {
|
|
496
631
|
/** Available options in the ColorPicker.*/
|
|
497
632
|
colorOptions: ColorOption[];
|
|
498
633
|
/** Preferred border radius of UI elements.*/
|
|
499
634
|
borderRadius: number;
|
|
500
|
-
/** The height of a single row in the board grid.
|
|
635
|
+
/** The height of a single row in the board grid. To know how many rows a widget occupies, use `instance.dynamic.current.size` instead. */
|
|
501
636
|
rowHeight: number;
|
|
637
|
+
/** Spacing between widgets in the board grid, in pixels. Use this to align columns within a widget with the board's columns. */
|
|
638
|
+
gridSpacing?: number;
|
|
502
639
|
/** Design settings related to icon badges. */
|
|
503
640
|
badge: {
|
|
504
641
|
/** Background color of an icon badge. */
|
package/lib/types/index.js
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CommandBarItemType = exports.CustomCommandBarItemSeverity = void 0;
|
|
3
|
+
exports.CommandBarItemType = exports.CustomCommandBarItemSeverity = exports.WidgetUserConfigAccess = exports.WidgetBodyRenderMode = exports.WidgetHeaderActionsMode = exports.WidgetHeaderRenderMode = void 0;
|
|
4
|
+
var WidgetHeaderRenderMode;
|
|
5
|
+
(function (WidgetHeaderRenderMode) {
|
|
6
|
+
/** A header bar at the top of the widget, showing the title and actions. */
|
|
7
|
+
WidgetHeaderRenderMode["Default"] = "default";
|
|
8
|
+
/** No header bar. Actions are shown on top of the widget body when hovering the widget. */
|
|
9
|
+
WidgetHeaderRenderMode["Overlay"] = "overlay";
|
|
10
|
+
})(WidgetHeaderRenderMode || (exports.WidgetHeaderRenderMode = WidgetHeaderRenderMode = {}));
|
|
11
|
+
var WidgetHeaderActionsMode;
|
|
12
|
+
(function (WidgetHeaderActionsMode) {
|
|
13
|
+
/** All actions available to the user. */
|
|
14
|
+
WidgetHeaderActionsMode["All"] = "all";
|
|
15
|
+
/** Only essential actions the user can currently perform; informational, secondary and disabled actions are hidden. */
|
|
16
|
+
WidgetHeaderActionsMode["Limited"] = "limited";
|
|
17
|
+
})(WidgetHeaderActionsMode || (exports.WidgetHeaderActionsMode = WidgetHeaderActionsMode = {}));
|
|
18
|
+
var WidgetBodyRenderMode;
|
|
19
|
+
(function (WidgetBodyRenderMode) {
|
|
20
|
+
/** The widget is rendered on a card, with a background and shadow. */
|
|
21
|
+
WidgetBodyRenderMode["Default"] = "default";
|
|
22
|
+
/** No background or shadow. The header is always rendered as `WidgetHeaderRenderMode.Overlay`. */
|
|
23
|
+
WidgetBodyRenderMode["Transparent"] = "transparent";
|
|
24
|
+
})(WidgetBodyRenderMode || (exports.WidgetBodyRenderMode = WidgetBodyRenderMode = {}));
|
|
25
|
+
var WidgetUserConfigAccess;
|
|
26
|
+
(function (WidgetUserConfigAccess) {
|
|
27
|
+
/** The widget has no user configuration (`isConfigurableByUser` is `false` in its manifest). */
|
|
28
|
+
WidgetUserConfigAccess["None"] = "none";
|
|
29
|
+
/** The current user can change this widget's user configuration. */
|
|
30
|
+
WidgetUserConfigAccess["Editable"] = "editable";
|
|
31
|
+
/** The current user normally can, but not right now, e.g. while another user edits the shared board or the SharePoint page is in edit mode. */
|
|
32
|
+
WidgetUserConfigAccess["Blocked"] = "blocked";
|
|
33
|
+
/** The current user can't change this widget's user configuration, e.g. when viewing someone else's shared board. */
|
|
34
|
+
WidgetUserConfigAccess["ReadOnly"] = "readOnly";
|
|
35
|
+
})(WidgetUserConfigAccess || (exports.WidgetUserConfigAccess = WidgetUserConfigAccess = {}));
|
|
4
36
|
/**
|
|
5
37
|
* Tells the severity of the command bar item, resulting in
|
|
6
38
|
* distinguishable presentation of the item
|
|
@@ -6,8 +6,8 @@ export declare class ConfigurationHelper {
|
|
|
6
6
|
/**
|
|
7
7
|
*
|
|
8
8
|
* @param config The serialized configuration to parse into an object
|
|
9
|
-
* @param
|
|
9
|
+
* @param _schema Deprecated: kept so existing two-argument callers still compile.
|
|
10
10
|
*/
|
|
11
|
-
static parseConfiguration<T>(config: string,
|
|
12
|
-
static stringifyConfiguration(config:
|
|
11
|
+
static parseConfiguration<T>(config: string, _schema?: unknown): T;
|
|
12
|
+
static stringifyConfiguration(config: unknown): string;
|
|
13
13
|
}
|
|
@@ -9,9 +9,9 @@ class ConfigurationHelper {
|
|
|
9
9
|
/**
|
|
10
10
|
*
|
|
11
11
|
* @param config The serialized configuration to parse into an object
|
|
12
|
-
* @param
|
|
12
|
+
* @param _schema Deprecated: kept so existing two-argument callers still compile.
|
|
13
13
|
*/
|
|
14
|
-
static parseConfiguration(config,
|
|
14
|
+
static parseConfiguration(config, _schema) {
|
|
15
15
|
const data = JSON.parse(config ? config : '{}');
|
|
16
16
|
return data;
|
|
17
17
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ichicraft/widgets-widget-base",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Part of the Widget Development Kit for building widgets for Bloom Intranet",
|
|
3
|
+
"version": "1.22.0",
|
|
4
|
+
"description": "Part of the Widget Development Kit for building widgets for Bloom Intranet. The base class and context types every widget implements.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"build:watch": "tsc --build --force --verbose --watch tsconfig.json tsconfig.dev.json",
|
|
10
10
|
"clean": "rimraf lib",
|
|
11
11
|
"pretty": "prettier --write \"./**/*.{js,jsx,mjs,cjs,ts,tsx,json}\"",
|
|
12
|
-
"prepublishOnly": "npm run clean && npm run build"
|
|
12
|
+
"prepublishOnly": "npm run clean && npm run build",
|
|
13
|
+
"lint": "eslint src"
|
|
13
14
|
},
|
|
14
15
|
"keywords": [
|
|
15
16
|
"ichicraft",
|
|
@@ -22,27 +23,22 @@
|
|
|
22
23
|
"lib/**/*",
|
|
23
24
|
"!lib/**/*.tsbuildinfo"
|
|
24
25
|
],
|
|
25
|
-
"overrides": {
|
|
26
|
-
"requirejs": "2.3.7",
|
|
27
|
-
"validator@<13.15.26": "13.15.26",
|
|
28
|
-
"z-schema@<5.0.5": "5.0.5"
|
|
29
|
-
},
|
|
30
26
|
"dependencies": {
|
|
31
|
-
"@ichicraft/caching": "~1.0
|
|
27
|
+
"@ichicraft/caching": "~1.2.0",
|
|
32
28
|
"@microsoft/microsoft-graph-client": "3.0.2",
|
|
33
|
-
"@microsoft/sp-http": "1.
|
|
29
|
+
"@microsoft/sp-http": "^1.23.2",
|
|
34
30
|
"@pnp/sp": "4.0.1"
|
|
35
31
|
},
|
|
36
32
|
"devDependencies": {
|
|
37
|
-
"@
|
|
33
|
+
"@eslint/js": "^10.0.1",
|
|
34
|
+
"@ianvs/prettier-plugin-sort-imports": "^4.7.1",
|
|
38
35
|
"@types/node": "^18.19.0",
|
|
39
|
-
"eslint": "
|
|
40
|
-
"eslint-config-prettier": "
|
|
41
|
-
"eslint-plugin-prettier": "5.
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"typescript": "~5.3.3",
|
|
36
|
+
"eslint": "^10.9.0",
|
|
37
|
+
"eslint-config-prettier": "^10.1.8",
|
|
38
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
39
|
+
"prettier": "^3.9.6",
|
|
40
|
+
"typescript": "^6.0.3",
|
|
41
|
+
"typescript-eslint": "^8.68.0",
|
|
46
42
|
"webpack": "^5.109.2",
|
|
47
43
|
"webpack-dev-server": "^5.2.6"
|
|
48
44
|
},
|