@eodash/eodash 5.2.0 → 5.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/client/components/DashboardLayout.vue +0 -1
- package/core/client/composables/index.js +53 -59
- package/core/client/eodashSTAC/EodashCollection.js +196 -94
- package/core/client/eodashSTAC/auth.js +86 -0
- package/core/client/eodashSTAC/createLayers.js +204 -4
- package/core/client/eodashSTAC/helpers.js +254 -62
- package/core/client/eodashSTAC/parquet.js +0 -13
- package/core/client/eodashSTAC/triggers.js +1 -1
- package/core/client/store/actions.js +14 -0
- package/core/client/store/stac.js +46 -8
- package/core/client/store/states.js +6 -0
- package/core/client/types.ts +206 -3
- package/core/client/utils/bands-editor/arithmetic.js +144 -0
- package/core/client/utils/bands-editor/colors.js +36 -0
- package/core/client/utils/bands-editor/dom.js +196 -0
- package/core/client/utils/bands-editor/exampleSchema.json +1320 -0
- package/core/client/utils/bands-editor/index.js +68 -0
- package/core/client/utils/bands-editor/rgb.js +102 -0
- package/core/client/utils/index.js +5 -2
- package/core/client/views/Dashboard.vue +1 -1
- package/core/client/vite-env.d.ts +122 -0
- package/dist/client/{DashboardLayout-Dq9Kfe6O.js → DashboardLayout-BAstYnhU.js} +4 -5
- package/dist/client/{DynamicWebComponent-DCBMXskE.js → DynamicWebComponent-7v4_DFqP.js} +1 -1
- package/dist/client/{EodashDatePicker-DtngxU6s.js → EodashDatePicker-IVHLv9UN.js} +20 -22
- package/dist/client/{EodashItemFilter-ClQebJQt.js → EodashItemFilter-BPMpnXjo.js} +46 -31
- package/dist/client/EodashLayerControl-CSnQh2tb.js +1517 -0
- package/dist/client/{EodashLayoutSwitcher-DQ8SfVDd.js → EodashLayoutSwitcher-CPpGM8Pb.js} +4 -4
- package/dist/client/EodashMapBtns-C_jyUJ2x.js +301 -0
- package/dist/client/{EodashStacInfo-Dt1nF06x.js → EodashStacInfo-DjuWc0Iz.js} +1 -1
- package/dist/client/EodashTimeSlider-CDh9Lf02.js +53 -0
- package/dist/client/{EodashTools-DV5ykmWc.js → EodashTools-DSvDUUlL.js} +10 -7
- package/dist/client/{ExportState-B6zZQUmE.js → ExportState-BhjxS0jG.js} +145 -120
- package/dist/client/{Footer-DNhXs8k6.js → Footer-C3PPcdjv.js} +1 -1
- package/dist/client/{Header-BjhN5JY4.js → Header-E5NbT7HE.js} +2 -2
- package/dist/client/MobileLayout-DY7OHr1k.js +118 -0
- package/dist/client/{PopUp-CgpvNr3o.js → PopUp-CSPXdqKI.js} +79 -43
- package/dist/client/{ProcessList-vecpxThi.js → ProcessList-C3HV7G0b.js} +5 -6
- package/dist/client/{VImg-CETuikH2.js → VImg-FoXcOnWF.js} +6 -3
- package/dist/client/{VMain-Ci9DyaGU.js → VMain-Ck2g1QOG.js} +1 -1
- package/dist/client/{VTooltip-J4ac48X7.js → VTooltip-F_1Zcvhp.js} +2 -2
- package/dist/client/{WidgetsContainer-CCML4TyV.js → WidgetsContainer-Cq9uZEuN.js} +1 -1
- package/dist/client/asWebComponent-DZeEbWG0.js +8895 -0
- package/dist/client/{async-B7jIrM53.js → async-Dk79llLt.js} +2 -2
- package/dist/client/easing-CH0-9wR8.js +35 -0
- package/dist/client/eo-dash.js +1 -1
- package/dist/client/{forwardRefs-BQclvjMq.js → forwardRefs-BbvoXHtj.js} +58 -45
- package/dist/client/{handling-BS24aG1q.js → handling-DxucYlYh.js} +12 -6
- package/dist/client/{helpers-wXK7Ywio.js → helpers-CI_7CUmn.js} +568 -281
- package/dist/client/index-BO5uGfUe.js +571 -0
- package/dist/client/{index-9KR-G20t.js → index-C13BiO9C.js} +2 -2
- package/dist/client/{index-4UCzZi8B.js → index-DcCcdbgR.js} +26 -13
- package/dist/client/{index-B2XpdgR6.js → index-KrGHjH-_.js} +63 -36
- package/dist/client/templates.js +82 -15
- package/dist/client/{transition-yBii4fu6.js → transition-Ctkv90El.js} +1 -1
- package/dist/node/cli.js +6 -6
- package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +24 -10
- package/dist/types/core/client/eodashSTAC/auth.d.ts +7 -0
- package/dist/types/core/client/eodashSTAC/createLayers.d.ts +15 -3
- package/dist/types/core/client/eodashSTAC/helpers.d.ts +47 -16
- package/dist/types/core/client/plugins/vuetify.d.ts +14 -14
- package/dist/types/core/client/store/actions.d.ts +2 -0
- package/dist/types/core/client/store/stac.d.ts +16 -7
- package/dist/types/core/client/store/states.d.ts +4 -0
- package/dist/types/core/client/types.d.ts +170 -2
- package/dist/types/core/client/utils/bands-editor/arithmetic.d.ts +8 -0
- package/dist/types/core/client/utils/bands-editor/colors.d.ts +15 -0
- package/dist/types/core/client/utils/bands-editor/dom.d.ts +42 -0
- package/dist/types/core/client/utils/bands-editor/index.d.ts +20 -0
- package/dist/types/core/client/utils/bands-editor/rgb.d.ts +15 -0
- package/dist/types/core/client/utils/index.d.ts +1 -1
- package/dist/types/templates/baseConfig.d.ts +87 -1
- package/dist/types/templates/expert.d.ts +6 -6
- package/dist/types/templates/explore.d.ts +67 -0
- package/dist/types/templates/index.d.ts +1 -1
- package/dist/types/templates/{light.d.ts → lite.d.ts} +5 -5
- package/dist/types/widgets/EodashItemCatalog/index.vue.d.ts +21 -0
- package/dist/types/widgets/EodashItemCatalog/methods/filters.d.ts +49 -0
- package/dist/types/widgets/EodashItemCatalog/methods/handlers.d.ts +4 -0
- package/dist/types/widgets/EodashItemCatalog/methods/map.d.ts +12 -0
- package/dist/types/widgets/EodashItemCatalog/types.d.ts +14 -0
- package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +2 -0
- package/dist/types/widgets/EodashMap/index.vue.d.ts +108 -2
- package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -1
- package/dist/types/widgets/EodashMap/methods/index.d.ts +1 -1
- package/dist/types/widgets/EodashProcess/methods/custom-endpoints/layers/eoxhub-workspaces-endpoint.d.ts +1 -1
- package/dist/types/widgets/EodashTimeSlider.vue.d.ts +7 -0
- package/dist/types/widgets/EodashTools.vue.d.ts +10 -10
- package/dist/types/widgets/ExportState.vue.d.ts +2 -0
- package/package.json +28 -27
- package/templates/baseConfig.js +10 -5
- package/templates/compare.js +2 -2
- package/templates/expert.js +5 -5
- package/templates/explore.js +62 -0
- package/templates/index.js +1 -1
- package/templates/{light.js → lite.js} +1 -1
- package/widgets/EodashDatePicker.vue +15 -18
- package/widgets/EodashItemCatalog/index.vue +161 -0
- package/widgets/EodashItemCatalog/methods/filters.js +216 -0
- package/widgets/EodashItemCatalog/methods/handlers.js +50 -0
- package/widgets/EodashItemCatalog/methods/map.js +144 -0
- package/widgets/EodashItemCatalog/types.ts +15 -0
- package/widgets/EodashItemFilter.vue +35 -28
- package/widgets/EodashLayerControl.vue +10 -6
- package/widgets/EodashLayoutSwitcher.vue +1 -1
- package/widgets/EodashMap/EodashMapBtns.vue +18 -9
- package/widgets/EodashMap/index.vue +22 -12
- package/widgets/EodashMap/methods/create-layers-config.js +9 -6
- package/widgets/EodashMap/methods/index.js +27 -13
- package/widgets/EodashProcess/index.vue +17 -1
- package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +9 -3
- package/widgets/EodashProcess/methods/handling.js +2 -0
- package/widgets/EodashProcess/methods/outputs.js +1 -0
- package/widgets/EodashTimeSlider.vue +40 -0
- package/widgets/EodashTools.vue +7 -3
- package/widgets/ExportState.vue +53 -22
- package/dist/client/EodashLayerControl-BLBds28C.js +0 -154
- package/dist/client/EodashMapBtns-B89_YBDw.js +0 -326
- package/dist/client/MobileLayout-JelB6w1G.js +0 -118
- package/dist/client/asWebComponent-ZyEzWOOf.js +0 -19092
package/core/client/types.ts
CHANGED
|
@@ -109,6 +109,14 @@ export interface TEodashDatePicker {
|
|
|
109
109
|
>["$props"];
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
/** @group Widgets */
|
|
113
|
+
export interface TEodashTimeSlider {
|
|
114
|
+
name: "EodashTimeSlider";
|
|
115
|
+
properties?: InstanceType<
|
|
116
|
+
typeof import("^/EodashTimeSlider.vue").default
|
|
117
|
+
>["$props"];
|
|
118
|
+
}
|
|
119
|
+
|
|
112
120
|
/** @group Widgets */
|
|
113
121
|
export interface TEodashItemFilter {
|
|
114
122
|
name: "EodashItemFilter";
|
|
@@ -164,6 +172,12 @@ export interface TEodashLayoutSwitcher {
|
|
|
164
172
|
typeof import("^/EodashLayoutSwitcher.vue").default
|
|
165
173
|
>["$props"];
|
|
166
174
|
}
|
|
175
|
+
export interface TEodashItemCatalog {
|
|
176
|
+
name: "EodashItemCatalog";
|
|
177
|
+
properties?: InstanceType<
|
|
178
|
+
typeof import("^/EodashItemCatalog/index.vue").default
|
|
179
|
+
>["$props"];
|
|
180
|
+
}
|
|
167
181
|
|
|
168
182
|
/** @group Widgets */
|
|
169
183
|
export interface TExportState {
|
|
@@ -201,9 +215,11 @@ export type ComponentWidget =
|
|
|
201
215
|
| TEodashMapBtns
|
|
202
216
|
| TEodashTools
|
|
203
217
|
| TEodashLayoutSwitcher
|
|
218
|
+
| TEodashItemCatalog
|
|
204
219
|
| TExportState
|
|
205
220
|
| TPopUp
|
|
206
|
-
| TWidgetsContainer
|
|
221
|
+
| TWidgetsContainer
|
|
222
|
+
| TEodashTimeSlider;
|
|
207
223
|
/**
|
|
208
224
|
* Widget type: `internal` API. Internal widgets are Vue components provided by
|
|
209
225
|
* eodash.
|
|
@@ -299,7 +315,14 @@ export interface Template {
|
|
|
299
315
|
export type MultiTemplates = Record<string, Template>;
|
|
300
316
|
|
|
301
317
|
/** @ignore */
|
|
302
|
-
export type StacEndpoint =
|
|
318
|
+
export type StacEndpoint =
|
|
319
|
+
| string
|
|
320
|
+
| {
|
|
321
|
+
endpoint: string;
|
|
322
|
+
api?: boolean;
|
|
323
|
+
rasterEndpoint?: string;
|
|
324
|
+
vectorEndpoint?: string;
|
|
325
|
+
};
|
|
303
326
|
|
|
304
327
|
/** @group Eodash */
|
|
305
328
|
export interface EodashFont {
|
|
@@ -444,7 +467,11 @@ export type EodashStyleJson = import("ol/style/flat").FlatStyleLike & {
|
|
|
444
467
|
jsonform?: import("json-schema").JSONSchema7;
|
|
445
468
|
tooltip?: { id: string; title?: string; appendix?: string }[];
|
|
446
469
|
};
|
|
447
|
-
|
|
470
|
+
export type EodashRasterJSONForm = {
|
|
471
|
+
jsonform: Record<string, any>;
|
|
472
|
+
legend?: import("@eox/layercontrol/src/components/layer-config.js").EOxLayerControlLayerConfig["layerConfig"]["legend"];
|
|
473
|
+
};
|
|
474
|
+
/** @ignore */
|
|
448
475
|
export type LayersEventBusKeys =
|
|
449
476
|
| "layers:updated"
|
|
450
477
|
| "time:updated"
|
|
@@ -452,3 +479,179 @@ export type LayersEventBusKeys =
|
|
|
452
479
|
| "compareLayers:updated"
|
|
453
480
|
| "compareTime:updated"
|
|
454
481
|
| "compareProcess:updated";
|
|
482
|
+
|
|
483
|
+
//// STAC API types
|
|
484
|
+
/** @ignore */
|
|
485
|
+
export interface SearchParams {
|
|
486
|
+
/** Collection IDs to search within */
|
|
487
|
+
collections: string[];
|
|
488
|
+
/** Query parameters */
|
|
489
|
+
query: {
|
|
490
|
+
datetime?: {
|
|
491
|
+
eq?: string;
|
|
492
|
+
in?: string[];
|
|
493
|
+
};
|
|
494
|
+
geometry?: Record<string, any>;
|
|
495
|
+
};
|
|
496
|
+
/** Maximum number of results to return */
|
|
497
|
+
limit?: number;
|
|
498
|
+
}
|
|
499
|
+
export interface StacItemsAPIResponse {
|
|
500
|
+
type: "FeatureCollection";
|
|
501
|
+
features: import("stac-ts").StacItem[];
|
|
502
|
+
}
|
|
503
|
+
/** @ignore */
|
|
504
|
+
export interface Render {
|
|
505
|
+
/** REQUIRED. Array of asset keys referencing the assets that are used to make the rendering */
|
|
506
|
+
assets: string[];
|
|
507
|
+
/** Optional title of the rendering */
|
|
508
|
+
title?: string;
|
|
509
|
+
/** 2 dimensions array of delimited Min,Max range per band. If not provided, the data will not be rescaled. */
|
|
510
|
+
rescale?: number[][];
|
|
511
|
+
/** Nodata value to use for the referenced assets. */
|
|
512
|
+
nodata?: number | string;
|
|
513
|
+
/** Color map identifier that must be applied for a raster band */
|
|
514
|
+
colormap_name?: string;
|
|
515
|
+
/** Color map JSON definition that must be applied for a raster band */
|
|
516
|
+
colormap?: Record<string, unknown>;
|
|
517
|
+
/** Color formula that must be applied for a raster band */
|
|
518
|
+
color_formula?: string;
|
|
519
|
+
/** Resampling algorithm to apply to the referenced assets. See GDAL resampling algorithm for some examples. */
|
|
520
|
+
resampling?: string;
|
|
521
|
+
/** Band arithmetic formula to apply to the referenced assets. */
|
|
522
|
+
expression?: string;
|
|
523
|
+
/** Zoom levels range applicable for the visualization */
|
|
524
|
+
minmax_zoom?: number[];
|
|
525
|
+
}
|
|
526
|
+
/** @ignore */
|
|
527
|
+
export interface TitilerSTACParameters {
|
|
528
|
+
/** STAC Item URL. Required */
|
|
529
|
+
url: string;
|
|
530
|
+
/** asset names. */
|
|
531
|
+
assets?: string[];
|
|
532
|
+
/** rio-tiler's math expression with asset names (e.g Asset1_b1/Asset2_b1). */
|
|
533
|
+
expression?: string;
|
|
534
|
+
/** tell rio-tiler that each asset is a 1 band dataset, so expression Asset1/Asset2 can be passed. */
|
|
535
|
+
asset_as_band?: boolean;
|
|
536
|
+
/** Per asset band math expression (e.g Asset1|1,2,3). */
|
|
537
|
+
asset_bidx?: string[];
|
|
538
|
+
/** Overwrite internal Nodata value. */
|
|
539
|
+
nodata?: string | number;
|
|
540
|
+
/** Apply dataset internal Scale/Offset. */
|
|
541
|
+
unscale?: boolean;
|
|
542
|
+
/** RasterIO resampling algorithm. Defaults to nearest. */
|
|
543
|
+
resampling?: string;
|
|
544
|
+
/** WarpKernel resampling algorithm (only used when doing re-projection). Defaults to nearest. */
|
|
545
|
+
reproject?: string;
|
|
546
|
+
/** Comma (',') delimited Min,Max range (e.g rescale=0,1000, rescale=0,1000&rescale=0,3000&rescale=0,2000). */
|
|
547
|
+
rescale?: string[];
|
|
548
|
+
/** rio-color formula. */
|
|
549
|
+
color_formula?: string;
|
|
550
|
+
/** JSON encoded custom Colormap. */
|
|
551
|
+
colormap?: string;
|
|
552
|
+
/** rio-tiler color map name. */
|
|
553
|
+
colormap_name?: string;
|
|
554
|
+
/** Add mask to the output data. Default is True. */
|
|
555
|
+
return_mask?: boolean;
|
|
556
|
+
/** Buffer on each side of the given tile. It must be a multiple of 0.5. Output tilesize will be expanded to tilesize + 2 * buffer (e.g 0.5 = 257x257, 1.0 = 258x258). */
|
|
557
|
+
buffer?: number;
|
|
558
|
+
/** Padding to apply to each tile edge. Helps reduce resampling artefacts along edges. Defaults to 0. */
|
|
559
|
+
padding?: number;
|
|
560
|
+
/** Custom algorithm name (e.g hillshade). */
|
|
561
|
+
algorithm?: string;
|
|
562
|
+
/** JSON encoded algorithm parameters. */
|
|
563
|
+
algorithm_params?: string;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Generic GeoJSON Feature interface that can hold additional properties.
|
|
567
|
+
* @ignore
|
|
568
|
+
*/
|
|
569
|
+
export interface GeoJsonFeature<T = Record<string, any>, G = GeoJSON.Geometry> {
|
|
570
|
+
type: "Feature";
|
|
571
|
+
geometry: G;
|
|
572
|
+
properties: T & Record<string, any>;
|
|
573
|
+
id?: string | number;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Generic GeoJSON FeatureCollection interface that can hold additional properties.
|
|
578
|
+
* @ignore
|
|
579
|
+
*/
|
|
580
|
+
export interface GeoJsonFeatureCollection<
|
|
581
|
+
T = Record<string, any>,
|
|
582
|
+
G = GeoJSON.Geometry,
|
|
583
|
+
> {
|
|
584
|
+
type: "FeatureCollection";
|
|
585
|
+
features: Array<GeoJsonFeature<T, G>>;
|
|
586
|
+
properties?: T & Record<string, any>;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Partial STAC Authentication Extension v1.1.0
|
|
590
|
+
* Generated from https://stac-extensions.github.io/authentication/v1.1.0/schema.json
|
|
591
|
+
*/
|
|
592
|
+
|
|
593
|
+
export interface AuthScheme {
|
|
594
|
+
/** Scheme keyword, e.g. http, s3, signedUrl, oauth2, apiKey, openIdConnect */
|
|
595
|
+
type:
|
|
596
|
+
| "http"
|
|
597
|
+
| "s3"
|
|
598
|
+
| "signedUrl"
|
|
599
|
+
| "oauth2"
|
|
600
|
+
| "apiKey"
|
|
601
|
+
| "openIdConnect"
|
|
602
|
+
| string;
|
|
603
|
+
|
|
604
|
+
description?: string;
|
|
605
|
+
|
|
606
|
+
name?: string;
|
|
607
|
+
in?: string;
|
|
608
|
+
|
|
609
|
+
scheme?: string;
|
|
610
|
+
|
|
611
|
+
flows?: Record<string, OAuth2Flow | SignedUrlFlow>;
|
|
612
|
+
|
|
613
|
+
openIdConnectUrl?: string;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
export interface OAuth2Flow {
|
|
617
|
+
authorizationUrl?: string;
|
|
618
|
+
tokenUrl?: string;
|
|
619
|
+
refreshUrl?: string;
|
|
620
|
+
scopes: Record<string, string>;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
/** Signed URL flow configuration */
|
|
625
|
+
export interface SignedUrlFlow {
|
|
626
|
+
authorizationApi: string;
|
|
627
|
+
method: string;
|
|
628
|
+
responseField?: string;
|
|
629
|
+
parameters?: Record<
|
|
630
|
+
string,
|
|
631
|
+
{
|
|
632
|
+
in: "query" | "header" | "body" | string;
|
|
633
|
+
required: boolean;
|
|
634
|
+
description?: string;
|
|
635
|
+
schema?: object;
|
|
636
|
+
}
|
|
637
|
+
>;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
export interface ApiKeyAuthScheme extends AuthScheme {
|
|
641
|
+
type: "apiKey",
|
|
642
|
+
name: string;
|
|
643
|
+
in: string;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
import { StacItem, StacLink, StacAsset } from "stac-ts";
|
|
647
|
+
export interface StacAuthItem extends StacItem {
|
|
648
|
+
"auth:schemes": {
|
|
649
|
+
[key: string]: AuthScheme;
|
|
650
|
+
},
|
|
651
|
+
}
|
|
652
|
+
export interface StacAuthLink extends StacLink {
|
|
653
|
+
"auth:refs": [string],
|
|
654
|
+
}
|
|
655
|
+
export interface StacAuthAsset extends StacAsset {
|
|
656
|
+
"auth:refs": [string],
|
|
657
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { addDraggableBands } from "./dom.js";
|
|
2
|
+
import { createSlotStyles, createSlot, fillSlotWithBand } from "./dom";
|
|
3
|
+
const MUSTACHE_REGEX = /\{\{([^}]+)\}\}/g;
|
|
4
|
+
/**
|
|
5
|
+
* Build the arithmetic expression interface
|
|
6
|
+
* @param {import("./index.js").BandsEditor} editor - The editor instance
|
|
7
|
+
* @param {Array<string>} colors - Array of color strings
|
|
8
|
+
* @param {Array<string>} bands - Array of band identifiers
|
|
9
|
+
* @param {Array<string>} bandTitles - Array of band titles
|
|
10
|
+
*/
|
|
11
|
+
export function buildArithmeticInterface(editor, colors, bands, bandTitles) {
|
|
12
|
+
const formulaTemplate = editor.schema.formulaTemplate || "{{A}}";
|
|
13
|
+
|
|
14
|
+
const style = createSlotStyles(bands, colors);
|
|
15
|
+
editor.control?.appendChild(style);
|
|
16
|
+
|
|
17
|
+
addDraggableBands(editor, bands, bandTitles);
|
|
18
|
+
|
|
19
|
+
editor.control?.appendChild(document.createElement("hr"));
|
|
20
|
+
|
|
21
|
+
// Add formula display with embedded slots after the bands
|
|
22
|
+
addFormulaSlots(editor, formulaTemplate, bands, bandTitles);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Generate the final formula string with band values substituted
|
|
27
|
+
* @param {import("./index.js").BandsEditor} editor - The editor instance
|
|
28
|
+
* @returns {string} Formula string with substituted values
|
|
29
|
+
*/
|
|
30
|
+
function generateFormulaString(editor) {
|
|
31
|
+
/** @type {string} */
|
|
32
|
+
const formulaTemplate = editor.schema.formulaTemplate || "{{A}}";
|
|
33
|
+
|
|
34
|
+
const variableValues = editor.variableValues || {};
|
|
35
|
+
|
|
36
|
+
return formulaTemplate.replace(MUSTACHE_REGEX, (match, variable) => {
|
|
37
|
+
const bandValue = variableValues[variable.trim()];
|
|
38
|
+
return bandValue || match; // Keep placeholder if no value assigned
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Add formula display with embedded circular slots
|
|
44
|
+
* @param {import("./index.js").BandsEditor} editor - The editor instance
|
|
45
|
+
* @param {string} template - Formula template string
|
|
46
|
+
* @param {Array<string>} bands - Array of band identifiers
|
|
47
|
+
* @param {Array<string>} bandTitles - Array of band titles
|
|
48
|
+
*/
|
|
49
|
+
function addFormulaSlots(editor, template, bands, bandTitles) {
|
|
50
|
+
const formulaContainer = document.createElement("div");
|
|
51
|
+
formulaContainer.classList.add("slots-container");
|
|
52
|
+
|
|
53
|
+
// Initialize slots tracking
|
|
54
|
+
editor.variableSlots = {};
|
|
55
|
+
|
|
56
|
+
// Split the template into parts and create elements
|
|
57
|
+
const parts = template.split(/(\{\{[^}]+\}\})/);
|
|
58
|
+
|
|
59
|
+
parts.forEach((part) => {
|
|
60
|
+
if (!part) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!part.match(MUSTACHE_REGEX)) {
|
|
65
|
+
// This is formula text
|
|
66
|
+
part = part.trim();
|
|
67
|
+
if (part) {
|
|
68
|
+
const textElement = document.createElement("span");
|
|
69
|
+
textElement.classList.add("formula-text");
|
|
70
|
+
textElement.textContent = part;
|
|
71
|
+
formulaContainer.appendChild(textElement);
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// This is a variable placeholder
|
|
77
|
+
const variable = part.replace(/[{}]/g, "").trim();
|
|
78
|
+
const slotElement = createSlot(variable, (e) => {
|
|
79
|
+
e.preventDefault();
|
|
80
|
+
const enumValue = e.dataTransfer?.getData("band");
|
|
81
|
+
if (!enumValue) return;
|
|
82
|
+
|
|
83
|
+
const enumIndex = bands.indexOf(enumValue);
|
|
84
|
+
const title = bandTitles[enumIndex] || enumValue;
|
|
85
|
+
|
|
86
|
+
editor.variableValues[variable] = enumValue;
|
|
87
|
+
|
|
88
|
+
// Update ALL slots for this variable using unified system
|
|
89
|
+
updateAllSlotsForVariable(editor, variable, enumValue, title);
|
|
90
|
+
|
|
91
|
+
// final formula string as the value
|
|
92
|
+
//@ts-expect-error todo
|
|
93
|
+
editor.value = generateFormulaString(editor);
|
|
94
|
+
editor.onChange(true);
|
|
95
|
+
});
|
|
96
|
+
formulaContainer.appendChild(slotElement);
|
|
97
|
+
|
|
98
|
+
// Track all slots for this variable
|
|
99
|
+
if (!editor.variableSlots[variable]) {
|
|
100
|
+
editor.variableSlots[variable] = [];
|
|
101
|
+
}
|
|
102
|
+
editor.variableSlots[variable].push(slotElement);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
editor.control?.appendChild(formulaContainer);
|
|
106
|
+
|
|
107
|
+
// Initialize slots with existing values after all slots are created
|
|
108
|
+
setTimeout(() => {
|
|
109
|
+
initializeSlots(editor);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Initialize all slots with existing values
|
|
115
|
+
* @param {import("./index.js").BandsEditor} editor - The editor instance
|
|
116
|
+
*/
|
|
117
|
+
function initializeSlots(editor) {
|
|
118
|
+
if (editor.variableValues && editor.variableSlots) {
|
|
119
|
+
Object.keys(editor.variableValues).forEach((variable) => {
|
|
120
|
+
const enumValue = editor.variableValues[variable];
|
|
121
|
+
const bands = editor.bands || editor.schema.enum || [];
|
|
122
|
+
const bandTitles =
|
|
123
|
+
editor.bandTitles || editor.schema.options?.enum_titles || bands;
|
|
124
|
+
const enumIndex = bands.indexOf(enumValue);
|
|
125
|
+
const title = bandTitles[enumIndex] || enumValue;
|
|
126
|
+
updateAllSlotsForVariable(editor, variable, enumValue, title);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Update all slots for a specific variable with band circle
|
|
133
|
+
* @param {import("./index.js").BandsEditor} editor - The editor instance
|
|
134
|
+
* @param {string} variable - Variable name
|
|
135
|
+
* @param {string} enumValue - Band value
|
|
136
|
+
* @param {string} title - Band title
|
|
137
|
+
*/
|
|
138
|
+
function updateAllSlotsForVariable(editor, variable, enumValue, title) {
|
|
139
|
+
if (editor.variableSlots && editor.variableSlots[variable]) {
|
|
140
|
+
editor.variableSlots[variable].forEach((slot) => {
|
|
141
|
+
fillSlotWithBand(slot, enumValue, title);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate band colors for the editor
|
|
3
|
+
* @param {Record<string,any>} schema - JSON schema
|
|
4
|
+
* @param {string} format - Format type ("bands" or "bands-arithmetic")
|
|
5
|
+
* @returns {string[]} Array of color strings
|
|
6
|
+
*/
|
|
7
|
+
export function generateBandColors(schema, format) {
|
|
8
|
+
const bands = format === "bands" ? schema.items?.enum : schema.enum || [];
|
|
9
|
+
const colors =
|
|
10
|
+
format === "bands"
|
|
11
|
+
? schema.items?.options?.colors
|
|
12
|
+
: schema.options?.colors || [];
|
|
13
|
+
if (colors && colors.length === bands.length) {
|
|
14
|
+
return colors;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return bands.map(
|
|
18
|
+
() =>
|
|
19
|
+
"#" +
|
|
20
|
+
Math.floor(Math.random() * 16777215)
|
|
21
|
+
.toString(16)
|
|
22
|
+
.padStart(6, "0"),
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get color for a specific band
|
|
28
|
+
* @param {string} band - Band identifier
|
|
29
|
+
* @param {string[]} bands - Array of band identifiers
|
|
30
|
+
* @param {string[]} colors - Array of color strings
|
|
31
|
+
* @returns {string} Color string
|
|
32
|
+
*/
|
|
33
|
+
export function getBandColor(band, bands, colors) {
|
|
34
|
+
const index = bands.indexOf(band);
|
|
35
|
+
return index !== -1 ? colors[index] : "#000000";
|
|
36
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { getBandColor } from "./colors.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create band styles
|
|
5
|
+
* @param {string[]} bands - Array of band identifiers
|
|
6
|
+
* @param {string[]} colors - Array of color strings
|
|
7
|
+
* @param {string} additionalStyles - Additional CSS styles
|
|
8
|
+
* @returns {HTMLStyleElement} Style element
|
|
9
|
+
*/
|
|
10
|
+
export function createBandStyles(bands, colors, additionalStyles = "") {
|
|
11
|
+
const style = document.createElement("style");
|
|
12
|
+
style.innerHTML = `
|
|
13
|
+
[data-band], [data-slot] {
|
|
14
|
+
display: inline-flex;
|
|
15
|
+
border: 1px solid darkgrey;
|
|
16
|
+
border-radius: 50%;
|
|
17
|
+
height: 40px;
|
|
18
|
+
aspect-ratio: 1/1;
|
|
19
|
+
padding: 4px;
|
|
20
|
+
margin: 2px;
|
|
21
|
+
align-items: center;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
cursor: move;
|
|
24
|
+
font-size: 10px;
|
|
25
|
+
}
|
|
26
|
+
${bands
|
|
27
|
+
.map(
|
|
28
|
+
(band) =>
|
|
29
|
+
`[data-band="${band}"] { background: ${getBandColor(
|
|
30
|
+
band,
|
|
31
|
+
bands,
|
|
32
|
+
colors,
|
|
33
|
+
)}; color: black; }`,
|
|
34
|
+
)
|
|
35
|
+
.join("\n")}
|
|
36
|
+
${additionalStyles}
|
|
37
|
+
`;
|
|
38
|
+
return style;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create a draggable band element.
|
|
43
|
+
* @param {string} enumValue
|
|
44
|
+
* @param {string} title
|
|
45
|
+
*/
|
|
46
|
+
export function createBandDiv(enumValue, title) {
|
|
47
|
+
const div = document.createElement("div");
|
|
48
|
+
div.dataset.band = enumValue;
|
|
49
|
+
div.textContent = title;
|
|
50
|
+
div.draggable = true;
|
|
51
|
+
div.ondragstart = (e) => {
|
|
52
|
+
e.dataTransfer?.setData("band", enumValue);
|
|
53
|
+
};
|
|
54
|
+
return div;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Add draggable band elements
|
|
59
|
+
* @param {import("./index.js").BandsEditor} editor - The editor instance
|
|
60
|
+
* @param {Array<string>} bands - Array of band identifiers
|
|
61
|
+
* @param {Array<string>} bandTitles - Array of band titles
|
|
62
|
+
*/
|
|
63
|
+
export function addDraggableBands(editor, bands, bandTitles) {
|
|
64
|
+
bands.forEach((band, index) => {
|
|
65
|
+
const title = bandTitles[index];
|
|
66
|
+
const bandDiv = createBandDiv(band, title);
|
|
67
|
+
|
|
68
|
+
// createBandDiv already sets up drag functionality
|
|
69
|
+
editor.control?.appendChild(bandDiv);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Create unified styles for all slot types
|
|
75
|
+
* @param {string[]} bands - Array of band identifiers
|
|
76
|
+
* @param {string[]} colors - Array of color strings
|
|
77
|
+
* @returns {HTMLStyleElement} Style element with unified slot styles
|
|
78
|
+
*/
|
|
79
|
+
export function createSlotStyles(bands, colors) {
|
|
80
|
+
const style = document.createElement("style");
|
|
81
|
+
style.innerHTML = `
|
|
82
|
+
/* Base styles for all band elements */
|
|
83
|
+
[data-band] {
|
|
84
|
+
display: inline-flex;
|
|
85
|
+
border: 1px solid darkgrey;
|
|
86
|
+
border-radius: 50%;
|
|
87
|
+
height: 40px;
|
|
88
|
+
aspect-ratio: 1/1;
|
|
89
|
+
padding: 4px;
|
|
90
|
+
margin: 2px;
|
|
91
|
+
align-items: center;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
cursor: move;
|
|
94
|
+
font-size: 10px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Band color styles */
|
|
98
|
+
${bands
|
|
99
|
+
.map(
|
|
100
|
+
(band) =>
|
|
101
|
+
`[data-band="${band}"] { background: ${getBandColor(
|
|
102
|
+
band,
|
|
103
|
+
bands,
|
|
104
|
+
colors,
|
|
105
|
+
)}; color: black; }`,
|
|
106
|
+
)
|
|
107
|
+
.join("\n")}
|
|
108
|
+
|
|
109
|
+
/* RGB slot styles */
|
|
110
|
+
[data-slot] {
|
|
111
|
+
display: inline-flex;
|
|
112
|
+
width: 50px;
|
|
113
|
+
height: 50px;
|
|
114
|
+
aspect-ratio: 1/1;
|
|
115
|
+
padding: 1px;
|
|
116
|
+
border: 2px solid #666;
|
|
117
|
+
background: #f0f0f0;
|
|
118
|
+
border-radius: 50%;
|
|
119
|
+
align-items: center;
|
|
120
|
+
justify-content: center;
|
|
121
|
+
cursor: pointer;
|
|
122
|
+
margin: 2px;
|
|
123
|
+
position: relative;
|
|
124
|
+
box-sizing: border-box;
|
|
125
|
+
}
|
|
126
|
+
[data-slot]:hover {
|
|
127
|
+
border-color: #333;
|
|
128
|
+
background: #f9f9f9;
|
|
129
|
+
}
|
|
130
|
+
[data-slot]::before {
|
|
131
|
+
content: attr(data-slot);
|
|
132
|
+
position: absolute;
|
|
133
|
+
font-size: 12px;
|
|
134
|
+
font-weight: bold;
|
|
135
|
+
color: #666;
|
|
136
|
+
z-index: 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* container */
|
|
140
|
+
.slots-container {
|
|
141
|
+
font-family: monospace;
|
|
142
|
+
font-size: 18px;
|
|
143
|
+
padding: 16px;
|
|
144
|
+
background: #f0f0f0;
|
|
145
|
+
border: 1px solid #ccc;
|
|
146
|
+
border-radius: 4px;
|
|
147
|
+
margin: 8px 0;
|
|
148
|
+
display: flex;
|
|
149
|
+
align-items: center;
|
|
150
|
+
justify-content: center;
|
|
151
|
+
flex-wrap: wrap;
|
|
152
|
+
gap: 4px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.formula-text {
|
|
156
|
+
font-size: 18px;
|
|
157
|
+
margin: 0 2px;
|
|
158
|
+
}
|
|
159
|
+
`;
|
|
160
|
+
return style;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Create a unified slot element for RGB or arithmetic use
|
|
165
|
+
* @param {string} identifier - RGB letter ("R", "G", "B") or variable name for arithmetic
|
|
166
|
+
* @param {(e: DragEvent) => void} onDrop - Drop handler function
|
|
167
|
+
* @returns {HTMLDivElement} Slot element
|
|
168
|
+
*/
|
|
169
|
+
export function createSlot(identifier, onDrop) {
|
|
170
|
+
const slotDiv = document.createElement("div");
|
|
171
|
+
// Use data-slot
|
|
172
|
+
slotDiv.dataset.slot = identifier;
|
|
173
|
+
|
|
174
|
+
// Add drag & drop functionality
|
|
175
|
+
slotDiv.ondrop = onDrop;
|
|
176
|
+
slotDiv.ondragover = (e) => e.preventDefault();
|
|
177
|
+
|
|
178
|
+
return slotDiv;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Fill a slot with a band
|
|
183
|
+
* @param {HTMLElement} slot - Slot element
|
|
184
|
+
* @param {string} enumValue - Band value
|
|
185
|
+
* @param {string} title - Band title
|
|
186
|
+
*/
|
|
187
|
+
export function fillSlotWithBand(slot, enumValue, title) {
|
|
188
|
+
// clear existing band and add new one
|
|
189
|
+
const existingBand = slot.querySelector("[data-band]");
|
|
190
|
+
if (existingBand) {
|
|
191
|
+
existingBand.remove();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const bandDiv = createBandDiv(enumValue, title);
|
|
195
|
+
slot.appendChild(bandDiv);
|
|
196
|
+
}
|