@superleapai/flow-ui 2.5.3 → 2.5.5
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/components/card-select.js +1 -1
- package/components/date-time-picker/date-time-picker.js +143 -11
- package/components/popover.js +31 -16
- package/components/select.js +9 -2
- package/components/time-picker.js +70 -17
- package/core/flow.js +9 -1
- package/dist/output.css +1 -1
- package/dist/superleap-flow.js +2229 -273
- package/dist/superleap-flow.js.map +1 -1
- package/dist/superleap-flow.min.js +2 -2
- package/index.d.ts +6 -0
- package/index.js +1 -0
- package/package.json +1 -1
package/dist/superleap-flow.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @superleapai/flow-ui v2.3
|
|
2
|
+
* @superleapai/flow-ui v2.5.3
|
|
3
3
|
* A reusable design system for building multi-step forms
|
|
4
4
|
*
|
|
5
5
|
* Copyright (c) 2024-present SuperLeap
|
|
6
6
|
* Licensed under MIT
|
|
7
7
|
*
|
|
8
8
|
* Build: development
|
|
9
|
-
* Date: 2026-02-
|
|
9
|
+
* Date: 2026-02-25T17:41:37.089Z
|
|
10
10
|
*
|
|
11
11
|
* For documentation and examples, visit:
|
|
12
12
|
* https://github.com/superleap/superleap-flow
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
'use strict';
|
|
16
16
|
|
|
17
17
|
// ============================================
|
|
18
|
-
// File 1/
|
|
18
|
+
// File 1/42: node_modules/superleap-sdk/superleap.js
|
|
19
19
|
// ============================================
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -2642,7 +2642,7 @@
|
|
|
2642
2642
|
|
|
2643
2643
|
|
|
2644
2644
|
// ============================================
|
|
2645
|
-
// File 2/
|
|
2645
|
+
// File 2/42: core/superleapClient.js
|
|
2646
2646
|
// ============================================
|
|
2647
2647
|
|
|
2648
2648
|
/**
|
|
@@ -2783,11 +2783,23 @@
|
|
|
2783
2783
|
return mergeConfig({}, DEFAULT_CONFIG);
|
|
2784
2784
|
}
|
|
2785
2785
|
|
|
2786
|
+
/**
|
|
2787
|
+
* Return the current base URL (from merged config after init).
|
|
2788
|
+
* Used by file-input and other components that build API URLs.
|
|
2789
|
+
*
|
|
2790
|
+
* @returns {string|null} baseUrl or null if not initialized
|
|
2791
|
+
*/
|
|
2792
|
+
function getBaseUrl() {
|
|
2793
|
+
if (_config && _config.baseUrl) return _config.baseUrl;
|
|
2794
|
+
return null;
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2786
2797
|
var superleapClient = {
|
|
2787
2798
|
init: init,
|
|
2788
2799
|
getSdk: getSdk,
|
|
2789
2800
|
isAvailable: isAvailable,
|
|
2790
2801
|
getDefaultConfig: getDefaultConfig,
|
|
2802
|
+
getBaseUrl: getBaseUrl,
|
|
2791
2803
|
};
|
|
2792
2804
|
|
|
2793
2805
|
if (global) {
|
|
@@ -2798,7 +2810,7 @@
|
|
|
2798
2810
|
|
|
2799
2811
|
|
|
2800
2812
|
// ============================================
|
|
2801
|
-
// File 3/
|
|
2813
|
+
// File 3/42: core/bridge.js
|
|
2802
2814
|
// ============================================
|
|
2803
2815
|
|
|
2804
2816
|
/**
|
|
@@ -3326,7 +3338,7 @@
|
|
|
3326
3338
|
|
|
3327
3339
|
|
|
3328
3340
|
// ============================================
|
|
3329
|
-
// File 4/
|
|
3341
|
+
// File 4/42: core/crm.js
|
|
3330
3342
|
// ============================================
|
|
3331
3343
|
|
|
3332
3344
|
/**
|
|
@@ -3669,7 +3681,7 @@
|
|
|
3669
3681
|
|
|
3670
3682
|
|
|
3671
3683
|
// ============================================
|
|
3672
|
-
// File 5/
|
|
3684
|
+
// File 5/42: components/label.js
|
|
3673
3685
|
// ============================================
|
|
3674
3686
|
|
|
3675
3687
|
/**
|
|
@@ -3786,7 +3798,7 @@
|
|
|
3786
3798
|
|
|
3787
3799
|
|
|
3788
3800
|
// ============================================
|
|
3789
|
-
// File 6/
|
|
3801
|
+
// File 6/42: core/flow.js
|
|
3790
3802
|
// ============================================
|
|
3791
3803
|
|
|
3792
3804
|
/**
|
|
@@ -4038,6 +4050,48 @@
|
|
|
4038
4050
|
return field;
|
|
4039
4051
|
}
|
|
4040
4052
|
|
|
4053
|
+
/**
|
|
4054
|
+
* Create a rich text editor field
|
|
4055
|
+
* @param {Object} config - Configuration object
|
|
4056
|
+
* @param {string} config.label - Field label
|
|
4057
|
+
* @param {string} config.fieldId - State key for this field
|
|
4058
|
+
* @param {string} [config.placeholder] - Placeholder when empty
|
|
4059
|
+
* @param {boolean} [config.required] - Whether field is required
|
|
4060
|
+
* @param {string} [config.helpText] - Optional help text for tooltip
|
|
4061
|
+
* @param {number} [config.minHeightPx] - Min height of editor area in pixels (default 400)
|
|
4062
|
+
* @param {boolean} [config.disabled] - Whether editor is disabled
|
|
4063
|
+
* @returns {HTMLElement} Field element
|
|
4064
|
+
*/
|
|
4065
|
+
function createRichTextEditor(config) {
|
|
4066
|
+
const { label, fieldId, placeholder, required = false, helpText = null, minHeightPx = 400, disabled = false } = config;
|
|
4067
|
+
|
|
4068
|
+
const field = createFieldWrapper(label, required, helpText);
|
|
4069
|
+
field.setAttribute("data-field-id", fieldId);
|
|
4070
|
+
|
|
4071
|
+
if (getComponent("RichTextEditorComponent") && getComponent("RichTextEditorComponent").create) {
|
|
4072
|
+
const currentValue = get(fieldId) || "";
|
|
4073
|
+
const editorEl = getComponent("RichTextEditorComponent").create({
|
|
4074
|
+
value: currentValue,
|
|
4075
|
+
placeholder: placeholder || "",
|
|
4076
|
+
minHeightPx,
|
|
4077
|
+
disabled,
|
|
4078
|
+
onChange: (html) => set(fieldId, html),
|
|
4079
|
+
});
|
|
4080
|
+
editorEl._fieldId = fieldId;
|
|
4081
|
+
field.appendChild(editorEl);
|
|
4082
|
+
return field;
|
|
4083
|
+
}
|
|
4084
|
+
|
|
4085
|
+
const fallback = document.createElement("textarea");
|
|
4086
|
+
fallback.className = "textarea min-h-[400px]";
|
|
4087
|
+
fallback.placeholder = placeholder || `Enter ${label.toLowerCase()}`;
|
|
4088
|
+
fallback.value = get(fieldId) || "";
|
|
4089
|
+
fallback.disabled = disabled;
|
|
4090
|
+
fallback.addEventListener("change", (e) => set(fieldId, e.target.value));
|
|
4091
|
+
field.appendChild(fallback);
|
|
4092
|
+
return field;
|
|
4093
|
+
}
|
|
4094
|
+
|
|
4041
4095
|
/**
|
|
4042
4096
|
* Create a select dropdown field (using custom select component)
|
|
4043
4097
|
* @param {Object} config - Configuration object
|
|
@@ -4339,6 +4393,81 @@
|
|
|
4339
4393
|
return field;
|
|
4340
4394
|
}
|
|
4341
4395
|
|
|
4396
|
+
/**
|
|
4397
|
+
* Create a card select field (uses CardSelect component when available, else radio fallback)
|
|
4398
|
+
* @param {Object} config - Configuration object
|
|
4399
|
+
* @param {string} config.label - Field label
|
|
4400
|
+
* @param {string} config.fieldId - State key for this field
|
|
4401
|
+
* @param {Array} config.options - Array of { value, label, description?, icon?, disabled? }
|
|
4402
|
+
* @param {boolean} [config.required] - Whether field is required
|
|
4403
|
+
* @param {Function} [config.onChange] - Optional change handler (receives selected value)
|
|
4404
|
+
* @param {string} [config.helpText] - Optional help text for tooltip
|
|
4405
|
+
* @param {boolean} [config.disabled] - Whether all cards are disabled
|
|
4406
|
+
* @param {string} [config.className] - Extra CSS class on card container
|
|
4407
|
+
* @returns {HTMLElement} Field wrapper element
|
|
4408
|
+
*/
|
|
4409
|
+
function createCardSelect(config) {
|
|
4410
|
+
const { label, fieldId, options = [], required = false, onChange, helpText = null, disabled = false, className } = config;
|
|
4411
|
+
|
|
4412
|
+
const field = createFieldWrapper(label, required, helpText);
|
|
4413
|
+
|
|
4414
|
+
if (getComponent("CardSelect") && getComponent("CardSelect").create) {
|
|
4415
|
+
const currentValue = get(fieldId);
|
|
4416
|
+
const cardSelectEl = getComponent("CardSelect").create({
|
|
4417
|
+
name: fieldId,
|
|
4418
|
+
options: options.map((opt) => ({
|
|
4419
|
+
value: opt.value,
|
|
4420
|
+
label: opt.label || opt.value,
|
|
4421
|
+
description: opt.description,
|
|
4422
|
+
icon: opt.icon,
|
|
4423
|
+
disabled: opt.disabled,
|
|
4424
|
+
})),
|
|
4425
|
+
value: currentValue,
|
|
4426
|
+
disabled,
|
|
4427
|
+
className,
|
|
4428
|
+
onChange: (value) => {
|
|
4429
|
+
set(fieldId, value);
|
|
4430
|
+
if (onChange) onChange(value);
|
|
4431
|
+
},
|
|
4432
|
+
});
|
|
4433
|
+
cardSelectEl._fieldId = fieldId;
|
|
4434
|
+
field.appendChild(cardSelectEl);
|
|
4435
|
+
return field;
|
|
4436
|
+
}
|
|
4437
|
+
|
|
4438
|
+
// Fallback: native radio buttons
|
|
4439
|
+
const radioGroup = document.createElement("div");
|
|
4440
|
+
radioGroup.className = "card-select-fallback";
|
|
4441
|
+
|
|
4442
|
+
options.forEach((opt) => {
|
|
4443
|
+
const wrapper = document.createElement("div");
|
|
4444
|
+
wrapper.className = "card-option";
|
|
4445
|
+
|
|
4446
|
+
const radio = document.createElement("input");
|
|
4447
|
+
radio.type = "radio";
|
|
4448
|
+
radio.name = fieldId;
|
|
4449
|
+
radio.value = opt.value;
|
|
4450
|
+
radio.id = `${fieldId}-${opt.value}`;
|
|
4451
|
+
radio.checked = get(fieldId) === opt.value;
|
|
4452
|
+
radio.disabled = disabled || !!opt.disabled;
|
|
4453
|
+
radio.addEventListener("change", () => {
|
|
4454
|
+
set(fieldId, opt.value);
|
|
4455
|
+
if (onChange) { onChange(opt.value); }
|
|
4456
|
+
});
|
|
4457
|
+
|
|
4458
|
+
const radioLabel = document.createElement("label");
|
|
4459
|
+
radioLabel.htmlFor = `${fieldId}-${opt.value}`;
|
|
4460
|
+
radioLabel.textContent = opt.label || opt.value;
|
|
4461
|
+
|
|
4462
|
+
wrapper.appendChild(radio);
|
|
4463
|
+
wrapper.appendChild(radioLabel);
|
|
4464
|
+
radioGroup.appendChild(wrapper);
|
|
4465
|
+
});
|
|
4466
|
+
|
|
4467
|
+
field.appendChild(radioGroup);
|
|
4468
|
+
return field;
|
|
4469
|
+
}
|
|
4470
|
+
|
|
4342
4471
|
/**
|
|
4343
4472
|
* Create a multi-select field (uses MultiSelect component when available, else checkbox group)
|
|
4344
4473
|
* @param {Object} config - Configuration object
|
|
@@ -4448,6 +4577,7 @@
|
|
|
4448
4577
|
size,
|
|
4449
4578
|
canClear,
|
|
4450
4579
|
initialLimit,
|
|
4580
|
+
initialFilter,
|
|
4451
4581
|
helpText = null,
|
|
4452
4582
|
} = config;
|
|
4453
4583
|
|
|
@@ -4467,6 +4597,7 @@
|
|
|
4467
4597
|
size: size || "default",
|
|
4468
4598
|
canClear: !!canClear,
|
|
4469
4599
|
initialLimit,
|
|
4600
|
+
initialFilter,
|
|
4470
4601
|
onChange: (value, record) => {
|
|
4471
4602
|
set(fieldId, value);
|
|
4472
4603
|
if (onChange) onChange(value, record);
|
|
@@ -4516,6 +4647,7 @@
|
|
|
4516
4647
|
variant,
|
|
4517
4648
|
size,
|
|
4518
4649
|
initialLimit,
|
|
4650
|
+
initialFilter,
|
|
4519
4651
|
displayFields,
|
|
4520
4652
|
helpText = null,
|
|
4521
4653
|
} = config;
|
|
@@ -4534,6 +4666,7 @@
|
|
|
4534
4666
|
variant: variant || "default",
|
|
4535
4667
|
size: size || "default",
|
|
4536
4668
|
initialLimit,
|
|
4669
|
+
initialFilter,
|
|
4537
4670
|
displayFields: displayFields || [],
|
|
4538
4671
|
onValuesChange: (values, records) => {
|
|
4539
4672
|
set(fieldId, values);
|
|
@@ -5091,6 +5224,40 @@
|
|
|
5091
5224
|
return field;
|
|
5092
5225
|
}
|
|
5093
5226
|
|
|
5227
|
+
/**
|
|
5228
|
+
* Create a checkbox group field (multiselect-like: options array, value array, onValuesChange)
|
|
5229
|
+
* @param {Object} config - { label, fieldId, options, required, helpText, variant, size, layout, disabled, onChange }
|
|
5230
|
+
* @returns {HTMLElement} Field wrapper containing checkbox group
|
|
5231
|
+
*/
|
|
5232
|
+
function createCheckboxGroup(config) {
|
|
5233
|
+
const { label, fieldId, options = [], required = false, helpText = null, variant, size, layout = "vertical", disabled = false, onChange } = config;
|
|
5234
|
+
|
|
5235
|
+
const field = createFieldWrapper(label, required, helpText);
|
|
5236
|
+
field.setAttribute("data-field-id", fieldId);
|
|
5237
|
+
|
|
5238
|
+
if (getComponent("CheckboxGroup") && getComponent("CheckboxGroup").create) {
|
|
5239
|
+
const currentValues = get(fieldId) || [];
|
|
5240
|
+
const groupEl = getComponent("CheckboxGroup").create({
|
|
5241
|
+
fieldId,
|
|
5242
|
+
options,
|
|
5243
|
+
value: currentValues,
|
|
5244
|
+
variant: variant || "default",
|
|
5245
|
+
size: size || "default",
|
|
5246
|
+
layout,
|
|
5247
|
+
disabled,
|
|
5248
|
+
onValuesChange: (values) => {
|
|
5249
|
+
set(fieldId, values);
|
|
5250
|
+
if (onChange) onChange(values);
|
|
5251
|
+
},
|
|
5252
|
+
});
|
|
5253
|
+
groupEl._fieldId = fieldId;
|
|
5254
|
+
field.appendChild(groupEl);
|
|
5255
|
+
return field;
|
|
5256
|
+
}
|
|
5257
|
+
|
|
5258
|
+
return field;
|
|
5259
|
+
}
|
|
5260
|
+
|
|
5094
5261
|
// ============================================================================
|
|
5095
5262
|
// STEPPER COMPONENT
|
|
5096
5263
|
// ============================================================================
|
|
@@ -5122,6 +5289,38 @@
|
|
|
5122
5289
|
});
|
|
5123
5290
|
}
|
|
5124
5291
|
|
|
5292
|
+
/**
|
|
5293
|
+
* Create a Tabs component (list + triggers + content panels)
|
|
5294
|
+
* @param {Object} config - { defaultValue?, value?, onChange?, tabs: [{ value, label, content }], size?, variant?, listClassName?, contentClassName? }
|
|
5295
|
+
* @returns {HTMLElement} Tabs root element
|
|
5296
|
+
*/
|
|
5297
|
+
function createTabs(config) {
|
|
5298
|
+
const Tabs = getComponent("Tabs");
|
|
5299
|
+
if (Tabs && typeof Tabs.create === "function") {
|
|
5300
|
+
return Tabs.create(config);
|
|
5301
|
+
}
|
|
5302
|
+
const fallback = document.createElement("div");
|
|
5303
|
+
fallback.className = "tabs-root";
|
|
5304
|
+
fallback.textContent = "Tabs component not loaded.";
|
|
5305
|
+
return fallback;
|
|
5306
|
+
}
|
|
5307
|
+
|
|
5308
|
+
/**
|
|
5309
|
+
* Create a Steps component (numbered step triggers + optional content panels)
|
|
5310
|
+
* @param {Object} config - { steps: [{ id, label, content? }], defaultValue?, value?, onChange?, size?, variant?, listClassName?, contentClassName?, showContent? }
|
|
5311
|
+
* @returns {HTMLElement} Steps root element
|
|
5312
|
+
*/
|
|
5313
|
+
function createSteps(config) {
|
|
5314
|
+
const Steps = getComponent("Steps");
|
|
5315
|
+
if (Steps && typeof Steps.create === "function") {
|
|
5316
|
+
return Steps.create(config);
|
|
5317
|
+
}
|
|
5318
|
+
const fallback = document.createElement("div");
|
|
5319
|
+
fallback.className = "steps-root";
|
|
5320
|
+
fallback.textContent = "Steps component not loaded.";
|
|
5321
|
+
return fallback;
|
|
5322
|
+
}
|
|
5323
|
+
|
|
5125
5324
|
// ============================================================================
|
|
5126
5325
|
// TABLE COMPONENT
|
|
5127
5326
|
// ============================================================================
|
|
@@ -5284,6 +5483,34 @@
|
|
|
5284
5483
|
return field;
|
|
5285
5484
|
}
|
|
5286
5485
|
|
|
5486
|
+
// ============================================================================
|
|
5487
|
+
// ALERTS
|
|
5488
|
+
// ============================================================================
|
|
5489
|
+
|
|
5490
|
+
/**
|
|
5491
|
+
* Render multiple alert messages into a container
|
|
5492
|
+
* @param {HTMLElement} container - Container to append alerts to
|
|
5493
|
+
* @param {string[]} messages - Array of message strings
|
|
5494
|
+
* @param {string} [variant='default'] - 'default' | 'error' | 'warning' | 'success' | 'info' | 'destructive'
|
|
5495
|
+
*/
|
|
5496
|
+
function renderAlerts(container, messages, variant = "default") {
|
|
5497
|
+
if (!container || !Array.isArray(messages)) return;
|
|
5498
|
+
const Alert = getComponent("Alert");
|
|
5499
|
+
if (Alert && typeof Alert.simple === "function") {
|
|
5500
|
+
messages.forEach((msg) => {
|
|
5501
|
+
const el = Alert.simple(msg, variant);
|
|
5502
|
+
if (el) container.appendChild(el);
|
|
5503
|
+
});
|
|
5504
|
+
} else {
|
|
5505
|
+
messages.forEach((msg) => {
|
|
5506
|
+
const div = document.createElement("div");
|
|
5507
|
+
div.className = "rounded border p-2 text-sm " + (variant === "error" ? "bg-red-50 border-red-200 text-red-800" : "bg-gray-50 border-gray-200");
|
|
5508
|
+
div.textContent = msg;
|
|
5509
|
+
container.appendChild(div);
|
|
5510
|
+
});
|
|
5511
|
+
}
|
|
5512
|
+
}
|
|
5513
|
+
|
|
5287
5514
|
// ============================================================================
|
|
5288
5515
|
// TOAST NOTIFICATIONS
|
|
5289
5516
|
// ============================================================================
|
|
@@ -5420,10 +5647,12 @@
|
|
|
5420
5647
|
// Form components
|
|
5421
5648
|
createInput,
|
|
5422
5649
|
createTextarea,
|
|
5650
|
+
createRichTextEditor,
|
|
5423
5651
|
createSelect,
|
|
5424
5652
|
createTimePicker,
|
|
5425
5653
|
createDateTimePicker,
|
|
5426
5654
|
createRadioGroup,
|
|
5655
|
+
createCardSelect,
|
|
5427
5656
|
createMultiSelect,
|
|
5428
5657
|
createRecordSelect,
|
|
5429
5658
|
createRecordMultiSelect,
|
|
@@ -5435,6 +5664,7 @@
|
|
|
5435
5664
|
createCurrency,
|
|
5436
5665
|
createPhoneInput,
|
|
5437
5666
|
createCheckbox,
|
|
5667
|
+
createCheckboxGroup,
|
|
5438
5668
|
|
|
5439
5669
|
// Button (delegates to Button component when available; resolved at call time via getComponent)
|
|
5440
5670
|
createButton: function (config) {
|
|
@@ -5455,8 +5685,11 @@
|
|
|
5455
5685
|
|
|
5456
5686
|
// Stepper
|
|
5457
5687
|
renderStepper,
|
|
5688
|
+
createTabs,
|
|
5689
|
+
createSteps,
|
|
5458
5690
|
|
|
5459
5691
|
// Alerts
|
|
5692
|
+
renderAlerts,
|
|
5460
5693
|
showToast,
|
|
5461
5694
|
|
|
5462
5695
|
// Table
|
|
@@ -5484,7 +5717,7 @@
|
|
|
5484
5717
|
|
|
5485
5718
|
|
|
5486
5719
|
// ============================================
|
|
5487
|
-
// File 7/
|
|
5720
|
+
// File 7/42: components/toast.js
|
|
5488
5721
|
// ============================================
|
|
5489
5722
|
|
|
5490
5723
|
/**
|
|
@@ -5833,7 +6066,7 @@
|
|
|
5833
6066
|
|
|
5834
6067
|
|
|
5835
6068
|
// ============================================
|
|
5836
|
-
// File 8/
|
|
6069
|
+
// File 8/42: components/alert.js
|
|
5837
6070
|
// ============================================
|
|
5838
6071
|
|
|
5839
6072
|
/**
|
|
@@ -6121,7 +6354,7 @@
|
|
|
6121
6354
|
|
|
6122
6355
|
|
|
6123
6356
|
// ============================================
|
|
6124
|
-
// File 9/
|
|
6357
|
+
// File 9/42: components/button.js
|
|
6125
6358
|
// ============================================
|
|
6126
6359
|
|
|
6127
6360
|
/**
|
|
@@ -6328,7 +6561,7 @@
|
|
|
6328
6561
|
|
|
6329
6562
|
|
|
6330
6563
|
// ============================================
|
|
6331
|
-
// File 10/
|
|
6564
|
+
// File 10/42: components/spinner.js
|
|
6332
6565
|
// ============================================
|
|
6333
6566
|
|
|
6334
6567
|
/**
|
|
@@ -6470,7 +6703,7 @@
|
|
|
6470
6703
|
|
|
6471
6704
|
|
|
6472
6705
|
// ============================================
|
|
6473
|
-
// File 11/
|
|
6706
|
+
// File 11/42: components/badge.js
|
|
6474
6707
|
// ============================================
|
|
6475
6708
|
|
|
6476
6709
|
/**
|
|
@@ -6611,7 +6844,7 @@
|
|
|
6611
6844
|
|
|
6612
6845
|
|
|
6613
6846
|
// ============================================
|
|
6614
|
-
// File 12/
|
|
6847
|
+
// File 12/42: components/avatar.js
|
|
6615
6848
|
// ============================================
|
|
6616
6849
|
|
|
6617
6850
|
/**
|
|
@@ -6812,7 +7045,7 @@
|
|
|
6812
7045
|
|
|
6813
7046
|
|
|
6814
7047
|
// ============================================
|
|
6815
|
-
// File 13/
|
|
7048
|
+
// File 13/42: components/icon.js
|
|
6816
7049
|
// ============================================
|
|
6817
7050
|
|
|
6818
7051
|
/**
|
|
@@ -6893,6 +7126,40 @@
|
|
|
6893
7126
|
/** Filled circle for "just color" mode (IconOrColor when only icon_color is set) */
|
|
6894
7127
|
IconCircleFilled:
|
|
6895
7128
|
'<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"><circle cx="12" cy="12" r="10" fill="currentColor"/></svg>',
|
|
7129
|
+
|
|
7130
|
+
// Rich text editor / toolbar (Tabler Icons outline, stroke 2)
|
|
7131
|
+
IconBold:
|
|
7132
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-bold"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 5h6a3.5 3.5 0 0 1 0 7h-6l0 -7" /><path d="M13 12h1a3.5 3.5 0 0 1 0 7h-7v-7" /></svg>',
|
|
7133
|
+
IconItalic:
|
|
7134
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-italic"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M11 5l6 0" /><path d="M7 19l6 0" /><path d="M14 5l-4 14" /></svg>',
|
|
7135
|
+
IconUnderline:
|
|
7136
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-underline"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 5v5a5 5 0 0 0 10 0v-5" /><path d="M5 19h14" /></svg>',
|
|
7137
|
+
IconH1:
|
|
7138
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-h-1"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M19 18v-8l-2 2" /><path d="M4 6v12" /><path d="M12 6v12" /><path d="M11 18h2" /><path d="M3 18h2" /><path d="M4 12h8" /><path d="M3 6h2" /><path d="M11 6h2" /></svg>',
|
|
7139
|
+
IconH2:
|
|
7140
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-h-2"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M17 12a2 2 0 1 1 4 0c0 .591 -.417 1.318 -.816 1.858l-3.184 4.143l4 0" /><path d="M4 6v12" /><path d="M12 6v12" /><path d="M11 18h2" /><path d="M3 18h2" /><path d="M4 12h8" /><path d="M3 6h2" /><path d="M11 6h2" /></svg>',
|
|
7141
|
+
IconH3:
|
|
7142
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-h-3"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M19 14a2 2 0 1 0 -2 -2" /><path d="M17 16a2 2 0 1 0 2 -2" /><path d="M4 6v12" /><path d="M12 6v12" /><path d="M11 18h2" /><path d="M3 18h2" /><path d="M4 12h8" /><path d="M3 6h2" /><path d="M11 6h2" /></svg>',
|
|
7143
|
+
IconList:
|
|
7144
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-list"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 6l11 0" /><path d="M9 12l11 0" /><path d="M9 18l11 0" /><path d="M5 6l0 .01" /><path d="M5 12l0 .01" /><path d="M5 18l0 .01" /></svg>',
|
|
7145
|
+
IconListNumbers:
|
|
7146
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-list-numbers"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M11 6h9" /><path d="M11 12h9" /><path d="M12 18h8" /><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4" /><path d="M6 10v-6l-2 2" /></svg>',
|
|
7147
|
+
IconAlignLeft:
|
|
7148
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-align-left"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 6l16 0" /><path d="M4 12l10 0" /><path d="M4 18l14 0" /></svg>',
|
|
7149
|
+
IconAlignCenter:
|
|
7150
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-align-center"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 6l16 0" /><path d="M8 12l8 0" /><path d="M6 18l12 0" /></svg>',
|
|
7151
|
+
IconAlignRight:
|
|
7152
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-align-right"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 6l16 0" /><path d="M10 12l10 0" /><path d="M6 18l14 0" /></svg>',
|
|
7153
|
+
IconCode:
|
|
7154
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-code"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 8l-4 4l4 4" /><path d="M17 8l4 4l-4 4" /><path d="M14 4l-4 16" /></svg>',
|
|
7155
|
+
IconLink:
|
|
7156
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-link"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 15l6 -6" /><path d="M11 6l.463 -.536a5 5 0 0 1 7.071 7.072l-.534 .464" /><path d="M13 18l-.397 .534a5.068 5.068 0 0 1 -7.127 0a4.972 4.972 0 0 1 0 -7.071l.524 -.463" /></svg>',
|
|
7157
|
+
IconPhoto:
|
|
7158
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-photo"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 8h.01" /><path d="M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12" /><path d="M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5" /><path d="M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3" /></svg>',
|
|
7159
|
+
IconArrowBackUp:
|
|
7160
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-arrow-back-up"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 14l-4 -4l4 -4" /><path d="M5 10h11a4 4 0 1 1 0 8h-1" /></svg>',
|
|
7161
|
+
IconArrowForwardUp:
|
|
7162
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-arrow-forward-up"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 14l4 -4l-4 -4" /><path d="M19 10h-11a4 4 0 1 0 0 8h1" /></svg>',
|
|
6896
7163
|
};
|
|
6897
7164
|
|
|
6898
7165
|
function join() {
|
|
@@ -7018,7 +7285,7 @@
|
|
|
7018
7285
|
|
|
7019
7286
|
|
|
7020
7287
|
// ============================================
|
|
7021
|
-
// File 14/
|
|
7288
|
+
// File 14/42: components/popover.js
|
|
7022
7289
|
// ============================================
|
|
7023
7290
|
|
|
7024
7291
|
/**
|
|
@@ -7041,6 +7308,7 @@
|
|
|
7041
7308
|
* @param {Function} [config.onOpen] - Called when popover opens (before positioning)
|
|
7042
7309
|
* @param {string} [config.bodyClassName] - Optional class for body wrapper (overrides default padding)
|
|
7043
7310
|
* @param {string} [config.panelClassName] - Optional class to add to panel (e.g. for width)
|
|
7311
|
+
* @param {boolean} [config.modal=false] - If true, lock body scroll and show backdrop; only popover and trigger are interactive
|
|
7044
7312
|
* @returns {Object} Popover API {show, hide, destroy, element}
|
|
7045
7313
|
*/
|
|
7046
7314
|
function create(config = {}) {
|
|
@@ -7055,6 +7323,7 @@
|
|
|
7055
7323
|
onOpen = null,
|
|
7056
7324
|
bodyClassName = "",
|
|
7057
7325
|
panelClassName = "",
|
|
7326
|
+
modal = true,
|
|
7058
7327
|
} = config;
|
|
7059
7328
|
|
|
7060
7329
|
const triggerEl =
|
|
@@ -7064,7 +7333,7 @@
|
|
|
7064
7333
|
return { show: noop, hide: noop, destroy: noop, element: null };
|
|
7065
7334
|
}
|
|
7066
7335
|
|
|
7067
|
-
// Wrap trigger in a relative container
|
|
7336
|
+
// Wrap trigger in a relative container for layout (full width); popover is portaled to body
|
|
7068
7337
|
const container = document.createElement("div");
|
|
7069
7338
|
container.className = "relative w-full";
|
|
7070
7339
|
const triggerParent = triggerEl.parentNode;
|
|
@@ -7075,7 +7344,7 @@
|
|
|
7075
7344
|
|
|
7076
7345
|
const wrapper = document.createElement("div");
|
|
7077
7346
|
wrapper.className =
|
|
7078
|
-
"
|
|
7347
|
+
"fixed z-50 pointer-events-none opacity-0 invisible transition-opacity duration-150 ease-out";
|
|
7079
7348
|
wrapper.setAttribute("aria-hidden", "true");
|
|
7080
7349
|
|
|
7081
7350
|
const panel = document.createElement("div");
|
|
@@ -7099,7 +7368,11 @@
|
|
|
7099
7368
|
const body = document.createElement("div");
|
|
7100
7369
|
body.className =
|
|
7101
7370
|
bodyClassName ||
|
|
7102
|
-
"text-reg-14 text-typography-secondary-text leading-5 [&_p]:mb-2 [&_p:last-child]:mb-0";
|
|
7371
|
+
"text-reg-14 text-typography-secondary-text leading-5 [&_p]:mb-2 [&_p:last-child]:mb-0 max-h-[90vh] overflow-y-auto overflow-x-hidden min-h-0";
|
|
7372
|
+
body.style.maxHeight = "90vh";
|
|
7373
|
+
body.style.overflowY = "auto";
|
|
7374
|
+
body.style.overflowX = "hidden";
|
|
7375
|
+
body.style.minHeight = "0";
|
|
7103
7376
|
if (panelClassName) {
|
|
7104
7377
|
panel.className = panel.className + " " + panelClassName;
|
|
7105
7378
|
}
|
|
@@ -7111,7 +7384,40 @@
|
|
|
7111
7384
|
panel.appendChild(body);
|
|
7112
7385
|
|
|
7113
7386
|
wrapper.appendChild(panel);
|
|
7114
|
-
|
|
7387
|
+
document.body.appendChild(wrapper);
|
|
7388
|
+
|
|
7389
|
+
var backdropEl = null;
|
|
7390
|
+
var resizeObserver = null;
|
|
7391
|
+
|
|
7392
|
+
function onBackdropWheel(e) {
|
|
7393
|
+
e.preventDefault();
|
|
7394
|
+
}
|
|
7395
|
+
|
|
7396
|
+
function applyModalOpen() {
|
|
7397
|
+
if (!modal) return;
|
|
7398
|
+
if (!backdropEl) {
|
|
7399
|
+
backdropEl = document.createElement("div");
|
|
7400
|
+
backdropEl.className =
|
|
7401
|
+
"fixed inset-0 z-40 bg-transparent pointer-events-auto";
|
|
7402
|
+
backdropEl.setAttribute("aria-hidden", "true");
|
|
7403
|
+
backdropEl.addEventListener("click", function () {
|
|
7404
|
+
hide();
|
|
7405
|
+
});
|
|
7406
|
+
backdropEl.addEventListener("wheel", onBackdropWheel, {
|
|
7407
|
+
passive: false,
|
|
7408
|
+
});
|
|
7409
|
+
}
|
|
7410
|
+
document.body.appendChild(backdropEl);
|
|
7411
|
+
wrapper.style.zIndex = "999";
|
|
7412
|
+
}
|
|
7413
|
+
|
|
7414
|
+
function applyModalClose() {
|
|
7415
|
+
if (!modal) return;
|
|
7416
|
+
if (backdropEl && backdropEl.parentNode) {
|
|
7417
|
+
backdropEl.parentNode.removeChild(backdropEl);
|
|
7418
|
+
}
|
|
7419
|
+
wrapper.style.zIndex = "";
|
|
7420
|
+
}
|
|
7115
7421
|
|
|
7116
7422
|
function noop() {}
|
|
7117
7423
|
|
|
@@ -7119,33 +7425,80 @@
|
|
|
7119
7425
|
const triggerRect = triggerEl.getBoundingClientRect();
|
|
7120
7426
|
const panelRect = panel.getBoundingClientRect();
|
|
7121
7427
|
const gap = 8;
|
|
7122
|
-
|
|
7123
|
-
|
|
7428
|
+
const viewportHeight =
|
|
7429
|
+
window.innerHeight || document.documentElement.clientHeight;
|
|
7430
|
+
const viewportWidth =
|
|
7431
|
+
window.innerWidth || document.documentElement.clientWidth;
|
|
7432
|
+
const spaceBelow = viewportHeight - triggerRect.bottom;
|
|
7433
|
+
const spaceAbove = triggerRect.top;
|
|
7434
|
+
const spaceRight = viewportWidth - triggerRect.right;
|
|
7435
|
+
const spaceLeft = triggerRect.left;
|
|
7436
|
+
|
|
7437
|
+
// Flip placement when there is not enough space (prefer requested side, flip only when needed)
|
|
7438
|
+
let effectivePlacement = placement;
|
|
7439
|
+
if (
|
|
7440
|
+
placement === "bottom" &&
|
|
7441
|
+
spaceBelow < panelRect.height + gap &&
|
|
7442
|
+
spaceAbove >= panelRect.height + gap
|
|
7443
|
+
) {
|
|
7444
|
+
effectivePlacement = "top";
|
|
7445
|
+
} else if (
|
|
7446
|
+
placement === "top" &&
|
|
7447
|
+
spaceAbove < panelRect.height + gap &&
|
|
7448
|
+
spaceBelow >= panelRect.height + gap
|
|
7449
|
+
) {
|
|
7450
|
+
effectivePlacement = "bottom";
|
|
7451
|
+
} else if (
|
|
7452
|
+
placement === "right" &&
|
|
7453
|
+
spaceRight < panelRect.width + gap &&
|
|
7454
|
+
spaceLeft >= panelRect.width + gap
|
|
7455
|
+
) {
|
|
7456
|
+
effectivePlacement = "left";
|
|
7457
|
+
} else if (
|
|
7458
|
+
placement === "left" &&
|
|
7459
|
+
spaceLeft < panelRect.width + gap &&
|
|
7460
|
+
spaceRight >= panelRect.width + gap
|
|
7461
|
+
) {
|
|
7462
|
+
effectivePlacement = "right";
|
|
7463
|
+
}
|
|
7124
7464
|
|
|
7125
|
-
|
|
7126
|
-
const alignLeft = (align === "center" ? (triggerRect.width - panelRect.width) / 2 : align === "end" ? triggerRect.width - panelRect.width : 0);
|
|
7127
|
-
const alignTop = (align === "center" ? (triggerRect.height - panelRect.height) / 2 : align === "end" ? triggerRect.height - panelRect.height : 0);
|
|
7465
|
+
panel.setAttribute("data-side", effectivePlacement);
|
|
7128
7466
|
|
|
7129
|
-
|
|
7467
|
+
let top = 0;
|
|
7468
|
+
let left = 0;
|
|
7469
|
+
const alignLeft =
|
|
7470
|
+
align === "center"
|
|
7471
|
+
? (triggerRect.width - panelRect.width) / 2
|
|
7472
|
+
: align === "end"
|
|
7473
|
+
? triggerRect.width - panelRect.width
|
|
7474
|
+
: 0;
|
|
7475
|
+
const alignTop =
|
|
7476
|
+
align === "center"
|
|
7477
|
+
? (triggerRect.height - panelRect.height) / 2
|
|
7478
|
+
: align === "end"
|
|
7479
|
+
? triggerRect.height - panelRect.height
|
|
7480
|
+
: 0;
|
|
7481
|
+
|
|
7482
|
+
switch (effectivePlacement) {
|
|
7130
7483
|
case "bottom":
|
|
7131
|
-
top = triggerRect.
|
|
7132
|
-
left = alignLeft;
|
|
7484
|
+
top = triggerRect.bottom + gap;
|
|
7485
|
+
left = triggerRect.left + alignLeft;
|
|
7133
7486
|
break;
|
|
7134
7487
|
case "top":
|
|
7135
|
-
top = -panelRect.height - gap;
|
|
7136
|
-
left = alignLeft;
|
|
7488
|
+
top = triggerRect.top - panelRect.height - gap;
|
|
7489
|
+
left = triggerRect.left + alignLeft;
|
|
7137
7490
|
break;
|
|
7138
7491
|
case "right":
|
|
7139
|
-
top = alignTop;
|
|
7140
|
-
left = triggerRect.
|
|
7492
|
+
top = triggerRect.top + alignTop;
|
|
7493
|
+
left = triggerRect.right + gap;
|
|
7141
7494
|
break;
|
|
7142
7495
|
case "left":
|
|
7143
|
-
top = alignTop;
|
|
7144
|
-
left = -panelRect.width - gap;
|
|
7496
|
+
top = triggerRect.top + alignTop;
|
|
7497
|
+
left = triggerRect.left - panelRect.width - gap;
|
|
7145
7498
|
break;
|
|
7146
7499
|
default:
|
|
7147
|
-
top = triggerRect.
|
|
7148
|
-
left = alignLeft;
|
|
7500
|
+
top = triggerRect.bottom + gap;
|
|
7501
|
+
left = triggerRect.left + alignLeft;
|
|
7149
7502
|
}
|
|
7150
7503
|
|
|
7151
7504
|
wrapper.style.transform = "";
|
|
@@ -7159,16 +7512,41 @@
|
|
|
7159
7512
|
wrapper.classList.add("invisible", "opacity-0", "pointer-events-none");
|
|
7160
7513
|
wrapper.classList.remove("visible", "opacity-100", "pointer-events-auto");
|
|
7161
7514
|
wrapper.setAttribute("aria-hidden", "true");
|
|
7515
|
+
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
7516
|
+
window.removeEventListener("resize", onScrollOrResize);
|
|
7517
|
+
if (resizeObserver && panel) {
|
|
7518
|
+
resizeObserver.disconnect();
|
|
7519
|
+
resizeObserver = null;
|
|
7520
|
+
}
|
|
7521
|
+
applyModalClose();
|
|
7162
7522
|
if (onClose) onClose();
|
|
7163
7523
|
}
|
|
7164
7524
|
|
|
7525
|
+
function onScrollOrResize() {
|
|
7526
|
+
if (wrapper.classList.contains("visible")) position();
|
|
7527
|
+
}
|
|
7528
|
+
|
|
7165
7529
|
function show() {
|
|
7166
7530
|
if (onOpen) onOpen();
|
|
7531
|
+
applyModalOpen();
|
|
7167
7532
|
requestAnimationFrame(function () {
|
|
7168
7533
|
position();
|
|
7169
|
-
wrapper.classList.remove(
|
|
7534
|
+
wrapper.classList.remove(
|
|
7535
|
+
"invisible",
|
|
7536
|
+
"opacity-0",
|
|
7537
|
+
"pointer-events-none",
|
|
7538
|
+
);
|
|
7170
7539
|
wrapper.classList.add("visible", "opacity-100", "pointer-events-auto");
|
|
7171
7540
|
wrapper.setAttribute("aria-hidden", "false");
|
|
7541
|
+
window.addEventListener("scroll", onScrollOrResize, true);
|
|
7542
|
+
window.addEventListener("resize", onScrollOrResize);
|
|
7543
|
+
// Re-position when panel content size changes (e.g. async record list load in record-select)
|
|
7544
|
+
if (typeof ResizeObserver !== "undefined" && !resizeObserver) {
|
|
7545
|
+
resizeObserver = new ResizeObserver(function () {
|
|
7546
|
+
if (wrapper.classList.contains("visible")) position();
|
|
7547
|
+
});
|
|
7548
|
+
resizeObserver.observe(panel);
|
|
7549
|
+
}
|
|
7172
7550
|
requestAnimationFrame(function () {
|
|
7173
7551
|
requestAnimationFrame(function () {
|
|
7174
7552
|
panel.setAttribute("data-state", "open");
|
|
@@ -7179,6 +7557,16 @@
|
|
|
7179
7557
|
|
|
7180
7558
|
function destroy() {
|
|
7181
7559
|
hide();
|
|
7560
|
+
applyModalClose();
|
|
7561
|
+
if (resizeObserver && panel) {
|
|
7562
|
+
resizeObserver.disconnect();
|
|
7563
|
+
resizeObserver = null;
|
|
7564
|
+
}
|
|
7565
|
+
if (backdropEl && backdropEl.parentNode) {
|
|
7566
|
+
backdropEl.parentNode.removeChild(backdropEl);
|
|
7567
|
+
}
|
|
7568
|
+
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
7569
|
+
window.removeEventListener("resize", onScrollOrResize);
|
|
7182
7570
|
if (wrapper.parentNode) {
|
|
7183
7571
|
wrapper.parentNode.removeChild(wrapper);
|
|
7184
7572
|
}
|
|
@@ -7228,6 +7616,8 @@
|
|
|
7228
7616
|
show,
|
|
7229
7617
|
hide,
|
|
7230
7618
|
destroy,
|
|
7619
|
+
/** Re-run positioning (e.g. after async content load). Call when panel size changes. */
|
|
7620
|
+
updatePosition: position,
|
|
7231
7621
|
setContent(newContent) {
|
|
7232
7622
|
body.innerHTML = "";
|
|
7233
7623
|
if (typeof newContent === "string") {
|
|
@@ -7249,7 +7639,7 @@
|
|
|
7249
7639
|
|
|
7250
7640
|
|
|
7251
7641
|
// ============================================
|
|
7252
|
-
// File 15/
|
|
7642
|
+
// File 15/42: components/select.js
|
|
7253
7643
|
// ============================================
|
|
7254
7644
|
|
|
7255
7645
|
/**
|
|
@@ -7446,11 +7836,11 @@
|
|
|
7446
7836
|
|
|
7447
7837
|
var content = document.createElement("div");
|
|
7448
7838
|
content.setAttribute("role", "listbox");
|
|
7449
|
-
content.className = "custom-select-content w-full max-h-[
|
|
7839
|
+
content.className = "custom-select-content w-full max-h-[45vh] overflow-hidden flex flex-col";
|
|
7450
7840
|
|
|
7451
7841
|
var optionsList = document.createElement("div");
|
|
7452
7842
|
optionsList.className =
|
|
7453
|
-
"overflow-y-auto max-h-[
|
|
7843
|
+
"overflow-y-auto max-h-[45vh] p-2 w-full rounded-4 bg-fill-quarternary-fill-white";
|
|
7454
7844
|
|
|
7455
7845
|
if (options.length === 0) {
|
|
7456
7846
|
var noOpt = document.createElement("div");
|
|
@@ -7509,7 +7899,7 @@
|
|
|
7509
7899
|
align: "start",
|
|
7510
7900
|
closeOnClickOutside: true,
|
|
7511
7901
|
bodyClassName: "p-0 overflow-hidden",
|
|
7512
|
-
panelClassName: "min-w-[var(--trigger-width)] max-h-[
|
|
7902
|
+
panelClassName: "min-w-[var(--trigger-width)] max-h-[45vh] overflow-hidden",
|
|
7513
7903
|
onOpen: function () {
|
|
7514
7904
|
if (disabled) {
|
|
7515
7905
|
popover.hide();
|
|
@@ -7807,7 +8197,7 @@
|
|
|
7807
8197
|
|
|
7808
8198
|
|
|
7809
8199
|
// ============================================
|
|
7810
|
-
// File 16/
|
|
8200
|
+
// File 16/42: components/enum-select.js
|
|
7811
8201
|
// ============================================
|
|
7812
8202
|
|
|
7813
8203
|
/**
|
|
@@ -8041,7 +8431,7 @@
|
|
|
8041
8431
|
// Create dropdown content
|
|
8042
8432
|
var content = document.createElement("div");
|
|
8043
8433
|
content.setAttribute("role", "listbox");
|
|
8044
|
-
content.className = "w-full min-w-[200px] max-h-[
|
|
8434
|
+
content.className = "w-full min-w-[200px] max-h-[45vh] overflow-hidden flex flex-col";
|
|
8045
8435
|
|
|
8046
8436
|
// Search input (using InputComponent like phone-input)
|
|
8047
8437
|
var searchContainer = document.createElement("div");
|
|
@@ -8102,7 +8492,7 @@
|
|
|
8102
8492
|
// Options list
|
|
8103
8493
|
var optionsList = document.createElement("div");
|
|
8104
8494
|
optionsList.className =
|
|
8105
|
-
"overflow-y-auto max-h-[
|
|
8495
|
+
"overflow-y-auto max-h-[45vh] p-2 w-full rounded-4 bg-fill-quarternary-fill-white flex-1 min-h-0";
|
|
8106
8496
|
|
|
8107
8497
|
content.appendChild(searchContainer);
|
|
8108
8498
|
content.appendChild(optionsList);
|
|
@@ -8590,7 +8980,7 @@
|
|
|
8590
8980
|
|
|
8591
8981
|
|
|
8592
8982
|
// ============================================
|
|
8593
|
-
// File 17/
|
|
8983
|
+
// File 17/42: components/record-select.js
|
|
8594
8984
|
// ============================================
|
|
8595
8985
|
|
|
8596
8986
|
/**
|
|
@@ -8604,9 +8994,20 @@
|
|
|
8604
8994
|
|
|
8605
8995
|
(function (global) {
|
|
8606
8996
|
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8997
|
+
function getDep(name) {
|
|
8998
|
+
if (
|
|
8999
|
+
typeof global.FlowUI !== "undefined" &&
|
|
9000
|
+
typeof global.FlowUI._getComponent === "function"
|
|
9001
|
+
) {
|
|
9002
|
+
var c = global.FlowUI._getComponent(name);
|
|
9003
|
+
if (c) return c;
|
|
9004
|
+
}
|
|
9005
|
+
return global[name];
|
|
9006
|
+
}
|
|
9007
|
+
|
|
9008
|
+
var Popover = getDep("Popover");
|
|
9009
|
+
var InputComponent = getDep("InputComponent");
|
|
9010
|
+
var Spinner = getDep("Spinner");
|
|
8610
9011
|
|
|
8611
9012
|
/** When objectSlug === USERS, show Vivid Avatar (name-based color) instead of static icon */
|
|
8612
9013
|
var STANDARD_OBJECT_SLUGS_USERS = "user";
|
|
@@ -8628,7 +9029,7 @@
|
|
|
8628
9029
|
'<svg width="16" height="16" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"/></svg>';
|
|
8629
9030
|
var X_SVG =
|
|
8630
9031
|
'<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" xmlns="http://www.w3.org/2000/svg"><path d="M18 6L6 18M6 6l12 12"/></svg>';
|
|
8631
|
-
|
|
9032
|
+
|
|
8632
9033
|
var SEARCH_ICON =
|
|
8633
9034
|
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>';
|
|
8634
9035
|
|
|
@@ -8643,7 +9044,8 @@
|
|
|
8643
9044
|
"border-error-border hover:border-error-border-hover focus:border-1/2 focus:border-error-border-hover",
|
|
8644
9045
|
warning:
|
|
8645
9046
|
"border-warning-border hover:border-warning-border-hover focus:border-1/2 focus:border-warning-border-hover",
|
|
8646
|
-
borderless:
|
|
9047
|
+
borderless:
|
|
9048
|
+
"border-none shadow-none rounded-0 bg-fill-quarternary-fill-white",
|
|
8647
9049
|
inline:
|
|
8648
9050
|
"focus:border-transparent border border-transparent shadow-none rounded-0 bg-fill-quarternary-fill-white hover:bg-fill-tertiary-fill-light-gray hover:border-transparent",
|
|
8649
9051
|
};
|
|
@@ -8652,7 +9054,9 @@
|
|
|
8652
9054
|
large: "px-12 py-8",
|
|
8653
9055
|
small: "px-8 py-4",
|
|
8654
9056
|
};
|
|
8655
|
-
var placeholderClass = placeholder
|
|
9057
|
+
var placeholderClass = placeholder
|
|
9058
|
+
? " text-typography-quaternary-text"
|
|
9059
|
+
: "";
|
|
8656
9060
|
var disabledClass = disabled
|
|
8657
9061
|
? " pointer-events-none cursor-not-allowed bg-fill-tertiary-fill-light-gray text-typography-quaternary-text hover:border-border-primary"
|
|
8658
9062
|
: "";
|
|
@@ -8708,15 +9112,27 @@
|
|
|
8708
9112
|
function getObjectIconInfo(slug, objectSchema) {
|
|
8709
9113
|
var color = "neutral";
|
|
8710
9114
|
var iconStr = "IconDatabase";
|
|
8711
|
-
if (
|
|
9115
|
+
if (
|
|
9116
|
+
objectSchema &&
|
|
9117
|
+
objectSchema.properties &&
|
|
9118
|
+
objectSchema.properties.icon_data
|
|
9119
|
+
) {
|
|
8712
9120
|
var iconData = objectSchema.properties.icon_data;
|
|
8713
|
-
if (typeof iconData.color === "string" && iconData.color)
|
|
8714
|
-
|
|
9121
|
+
if (typeof iconData.color === "string" && iconData.color)
|
|
9122
|
+
color = iconData.color;
|
|
9123
|
+
if (typeof iconData.icon === "string" && iconData.icon)
|
|
9124
|
+
iconStr = iconData.icon;
|
|
8715
9125
|
}
|
|
8716
|
-
if (
|
|
9126
|
+
if (
|
|
9127
|
+
!objectSchema ||
|
|
9128
|
+
!objectSchema.properties ||
|
|
9129
|
+
!objectSchema.properties.icon_data ||
|
|
9130
|
+
!objectSchema.properties.icon_data.icon
|
|
9131
|
+
) {
|
|
8717
9132
|
if (OBJECT_SLUG_TO_ICON[slug]) {
|
|
8718
9133
|
iconStr = OBJECT_SLUG_TO_ICON[slug].iconStr;
|
|
8719
|
-
if (OBJECT_SLUG_TO_ICON[slug].color)
|
|
9134
|
+
if (OBJECT_SLUG_TO_ICON[slug].color)
|
|
9135
|
+
color = OBJECT_SLUG_TO_ICON[slug].color;
|
|
8720
9136
|
} else {
|
|
8721
9137
|
iconStr = "IconDatabase";
|
|
8722
9138
|
color = "neutral";
|
|
@@ -8739,6 +9155,7 @@
|
|
|
8739
9155
|
* @param {string} [config.size] - 'default' | 'large' | 'small'
|
|
8740
9156
|
* @param {boolean} [config.canClear] - Show clear button when value is set
|
|
8741
9157
|
* @param {number} [config.initialLimit] - Initial fetch limit (default 50)
|
|
9158
|
+
* @param {Object} [config.initialFilter] - Optional filter object to merge with search (e.g. { field: "status", operator: "exact", value: "active" } or { and: [...] })
|
|
8742
9159
|
* @param {Object} [config.objectSchema] - Optional object type/schema; properties.icon_data { svg?, color? } used for static icon (not used for user; user shows Vivid Avatar)
|
|
8743
9160
|
* @returns {HTMLElement} Record select container element
|
|
8744
9161
|
*/
|
|
@@ -8747,12 +9164,14 @@
|
|
|
8747
9164
|
var objectSlug = config.objectSlug;
|
|
8748
9165
|
var objectSchema = config.objectSchema || null;
|
|
8749
9166
|
var placeholder = config.placeholder || "Select a record";
|
|
8750
|
-
var searchPlaceholder =
|
|
9167
|
+
var searchPlaceholder =
|
|
9168
|
+
config.searchPlaceholder || "Search " + (objectSlug || "") + "...";
|
|
8751
9169
|
var onChange = config.onChange;
|
|
8752
9170
|
var variant = config.variant || "default";
|
|
8753
9171
|
var size = config.size || "default";
|
|
8754
9172
|
var canClear = !!config.canClear;
|
|
8755
9173
|
var initialLimit = config.initialLimit != null ? config.initialLimit : 50;
|
|
9174
|
+
var initialFilter = config.initialFilter || null; // Can be array, object, or function returning either
|
|
8756
9175
|
|
|
8757
9176
|
var disabled = config.disabled === true;
|
|
8758
9177
|
var value =
|
|
@@ -8800,7 +9219,7 @@
|
|
|
8800
9219
|
size,
|
|
8801
9220
|
disabled,
|
|
8802
9221
|
!value,
|
|
8803
|
-
canClear && !!value && !disabled
|
|
9222
|
+
canClear && !!value && !disabled,
|
|
8804
9223
|
);
|
|
8805
9224
|
trigger.disabled = disabled;
|
|
8806
9225
|
trigger.setAttribute("aria-haspopup", "listbox");
|
|
@@ -8809,7 +9228,8 @@
|
|
|
8809
9228
|
trigger.classList.add("record-select-trigger");
|
|
8810
9229
|
|
|
8811
9230
|
var triggerContent = document.createElement("div");
|
|
8812
|
-
triggerContent.className =
|
|
9231
|
+
triggerContent.className =
|
|
9232
|
+
"record-select-trigger-content flex items-center gap-8 flex-1 min-w-0";
|
|
8813
9233
|
|
|
8814
9234
|
var triggerIcon = document.createElement("span");
|
|
8815
9235
|
triggerIcon.className = "record-select-trigger-icon shrink-0 hidden";
|
|
@@ -8852,7 +9272,9 @@
|
|
|
8852
9272
|
// Dropdown content: search + list (same content pattern as Select)
|
|
8853
9273
|
var content = document.createElement("div");
|
|
8854
9274
|
content.setAttribute("role", "listbox");
|
|
8855
|
-
content.
|
|
9275
|
+
content.setAttribute("data-field-id", fieldId);
|
|
9276
|
+
content.className =
|
|
9277
|
+
"record-select-content max-h-[45vh] overflow-hidden flex flex-col";
|
|
8856
9278
|
|
|
8857
9279
|
var searchWrap = document.createElement("div");
|
|
8858
9280
|
searchWrap.className = "py-8 border-b-1/2 border-border-primary";
|
|
@@ -8883,12 +9305,12 @@
|
|
|
8883
9305
|
} else {
|
|
8884
9306
|
var fallbackWrapper = document.createElement("div");
|
|
8885
9307
|
fallbackWrapper.className = "flex items-center gap-8 px-12";
|
|
8886
|
-
|
|
9308
|
+
|
|
8887
9309
|
var searchIconSpan = document.createElement("span");
|
|
8888
9310
|
searchIconSpan.className = "shrink-0 text-typography-tertiary-text";
|
|
8889
9311
|
searchIconSpan.innerHTML = SEARCH_ICON;
|
|
8890
9312
|
fallbackWrapper.appendChild(searchIconSpan);
|
|
8891
|
-
|
|
9313
|
+
|
|
8892
9314
|
var searchInput = document.createElement("input");
|
|
8893
9315
|
searchInput.type = "text";
|
|
8894
9316
|
searchInput.className =
|
|
@@ -8902,21 +9324,22 @@
|
|
|
8902
9324
|
content.appendChild(searchWrap);
|
|
8903
9325
|
|
|
8904
9326
|
var optionsList = document.createElement("div");
|
|
8905
|
-
optionsList.className =
|
|
8906
|
-
|
|
9327
|
+
optionsList.className =
|
|
9328
|
+
"overflow-y-auto max-h-[45vh] p-2 w-full rounded-4 bg-fill-quarternary-fill-white record-select-options";
|
|
9329
|
+
|
|
8907
9330
|
// Add scroll listener for infinite scroll
|
|
8908
9331
|
optionsList.addEventListener("scroll", function () {
|
|
8909
9332
|
if (isFetchingMore || !hasMoreRecords) return;
|
|
8910
9333
|
var scrollHeight = optionsList.scrollHeight;
|
|
8911
9334
|
var scrollTop = optionsList.scrollTop;
|
|
8912
9335
|
var clientHeight = optionsList.clientHeight;
|
|
8913
|
-
|
|
9336
|
+
|
|
8914
9337
|
// Trigger load more when scrolled to bottom (with 50px threshold)
|
|
8915
9338
|
if (scrollTop + clientHeight >= scrollHeight - 50) {
|
|
8916
9339
|
loadMoreRecords();
|
|
8917
9340
|
}
|
|
8918
9341
|
});
|
|
8919
|
-
|
|
9342
|
+
|
|
8920
9343
|
content.appendChild(optionsList);
|
|
8921
9344
|
|
|
8922
9345
|
popover = Popover.create({
|
|
@@ -8926,30 +9349,41 @@
|
|
|
8926
9349
|
align: "start",
|
|
8927
9350
|
closeOnClickOutside: true,
|
|
8928
9351
|
bodyClassName: "p-0 overflow-hidden",
|
|
8929
|
-
panelClassName: "
|
|
9352
|
+
panelClassName: "min-w-[var(--trigger-width)] overflow-hidden",
|
|
8930
9353
|
onOpen: function () {
|
|
8931
9354
|
if (disabled) {
|
|
8932
9355
|
popover.hide();
|
|
8933
9356
|
return;
|
|
8934
9357
|
}
|
|
8935
|
-
document.querySelectorAll(".custom-select.open, .record-select.open").forEach(function (other) {
|
|
8936
|
-
if (other !== container) {
|
|
8937
|
-
other.classList.remove("open");
|
|
8938
|
-
var t = other.querySelector("button, .custom-select-trigger, .record-select-trigger");
|
|
8939
|
-
if (t) t.setAttribute("aria-expanded", "false");
|
|
8940
|
-
}
|
|
8941
|
-
});
|
|
8942
9358
|
isOpen = true;
|
|
8943
9359
|
container.classList.add("open");
|
|
8944
9360
|
trigger.setAttribute("aria-expanded", "true");
|
|
8945
9361
|
searchTerm = "";
|
|
8946
9362
|
if (searchInputWrapper) searchInputWrapper.setValue("");
|
|
8947
9363
|
else if (searchInputEl) searchInputEl.value = "";
|
|
8948
|
-
|
|
9364
|
+
if (popover.panel) {
|
|
9365
|
+
var triggerWidthPx = trigger.offsetWidth + "px";
|
|
9366
|
+
popover.panel.style.setProperty("--trigger-width", triggerWidthPx);
|
|
9367
|
+
popover.panel.style.minWidth = triggerWidthPx;
|
|
9368
|
+
popover.panel.style.width = triggerWidthPx;
|
|
9369
|
+
}
|
|
8949
9370
|
loadInitialAndRender();
|
|
8950
9371
|
setTimeout(function () {
|
|
8951
9372
|
if (searchInputEl) searchInputEl.focus();
|
|
8952
9373
|
}, 0);
|
|
9374
|
+
// Let consumers (e.g. BANT Questions "Add Contact") inject content into the dropdown
|
|
9375
|
+
try {
|
|
9376
|
+
var doc =
|
|
9377
|
+
global.document ||
|
|
9378
|
+
(typeof document !== "undefined" ? document : null);
|
|
9379
|
+
if (doc && typeof global.CustomEvent !== "undefined") {
|
|
9380
|
+
doc.dispatchEvent(
|
|
9381
|
+
new global.CustomEvent("record-select:opened", {
|
|
9382
|
+
detail: { fieldId: fieldId, content: content },
|
|
9383
|
+
}),
|
|
9384
|
+
);
|
|
9385
|
+
}
|
|
9386
|
+
} catch (e) {}
|
|
8953
9387
|
},
|
|
8954
9388
|
onClose: function () {
|
|
8955
9389
|
isOpen = false;
|
|
@@ -8965,7 +9399,8 @@
|
|
|
8965
9399
|
},
|
|
8966
9400
|
});
|
|
8967
9401
|
|
|
8968
|
-
if (clearBtn)
|
|
9402
|
+
if (clearBtn)
|
|
9403
|
+
clearBtn.style.display = canClear && value && !disabled ? "" : "none";
|
|
8969
9404
|
|
|
8970
9405
|
function setValue(newVal) {
|
|
8971
9406
|
value = newVal !== undefined && newVal !== null ? newVal : "";
|
|
@@ -8979,16 +9414,18 @@
|
|
|
8979
9414
|
|
|
8980
9415
|
function updateTriggerDisplay() {
|
|
8981
9416
|
if (selectedRecord) {
|
|
8982
|
-
triggerText.textContent =
|
|
9417
|
+
triggerText.textContent =
|
|
9418
|
+
selectedRecord.name || selectedRecord.label || value;
|
|
8983
9419
|
trigger.classList.remove("placeholder");
|
|
8984
9420
|
trigger.className = triggerClasses(
|
|
8985
9421
|
variant,
|
|
8986
9422
|
size,
|
|
8987
9423
|
disabled,
|
|
8988
9424
|
false,
|
|
8989
|
-
canClear && !!value && !disabled
|
|
9425
|
+
canClear && !!value && !disabled,
|
|
8990
9426
|
);
|
|
8991
|
-
triggerIcon.className =
|
|
9427
|
+
triggerIcon.className =
|
|
9428
|
+
"record-select-trigger-icon shrink-0 flex items-center justify-center size-20 rounded-4 overflow-hidden";
|
|
8992
9429
|
triggerIcon.innerHTML = "";
|
|
8993
9430
|
if (objectSlug === STANDARD_OBJECT_SLUGS_USERS) {
|
|
8994
9431
|
var Avatar = getAvatar();
|
|
@@ -9000,7 +9437,9 @@
|
|
|
9000
9437
|
});
|
|
9001
9438
|
triggerIcon.appendChild(vividEl);
|
|
9002
9439
|
} else {
|
|
9003
|
-
renderStaticIconPlaceholder(
|
|
9440
|
+
renderStaticIconPlaceholder(
|
|
9441
|
+
selectedRecord.name || selectedRecord.label,
|
|
9442
|
+
);
|
|
9004
9443
|
}
|
|
9005
9444
|
} else {
|
|
9006
9445
|
renderStaticObjectIcon();
|
|
@@ -9013,12 +9452,13 @@
|
|
|
9013
9452
|
size,
|
|
9014
9453
|
disabled,
|
|
9015
9454
|
true,
|
|
9016
|
-
canClear && !!value && !disabled
|
|
9455
|
+
canClear && !!value && !disabled,
|
|
9017
9456
|
);
|
|
9018
9457
|
triggerIcon.className = "record-select-trigger-icon shrink-0 hidden";
|
|
9019
9458
|
triggerIcon.innerHTML = "";
|
|
9020
9459
|
}
|
|
9021
|
-
if (clearBtn)
|
|
9460
|
+
if (clearBtn)
|
|
9461
|
+
clearBtn.style.display = canClear && value && !disabled ? "" : "none";
|
|
9022
9462
|
}
|
|
9023
9463
|
|
|
9024
9464
|
function renderStaticObjectIcon() {
|
|
@@ -9055,18 +9495,39 @@
|
|
|
9055
9495
|
var fields = ["id", "name"];
|
|
9056
9496
|
var actualLimit = limit || initialLimit;
|
|
9057
9497
|
var offset = page ? (page - 1) * actualLimit : 0;
|
|
9058
|
-
|
|
9498
|
+
|
|
9059
9499
|
try {
|
|
9060
9500
|
if (model && typeof model.select === "function") {
|
|
9061
9501
|
var q = model.select.apply(model, fields);
|
|
9502
|
+
var filters = [];
|
|
9503
|
+
var resolvedFilter =
|
|
9504
|
+
typeof initialFilter === "function"
|
|
9505
|
+
? initialFilter()
|
|
9506
|
+
: initialFilter;
|
|
9507
|
+
console.log(
|
|
9508
|
+
"[RecordSelect] initialFilter:",
|
|
9509
|
+
resolvedFilter,
|
|
9510
|
+
"| search:",
|
|
9511
|
+
search,
|
|
9512
|
+
);
|
|
9513
|
+
if (resolvedFilter) {
|
|
9514
|
+
filters = filters.concat(
|
|
9515
|
+
Array.isArray(resolvedFilter) ? resolvedFilter : [resolvedFilter],
|
|
9516
|
+
);
|
|
9517
|
+
}
|
|
9062
9518
|
if (search && search.trim()) {
|
|
9063
|
-
|
|
9519
|
+
filters.push({
|
|
9064
9520
|
or: [
|
|
9065
9521
|
{ field: "name", operator: "contains", value: search.trim() },
|
|
9066
9522
|
{ field: "id", operator: "eq", value: search.trim() },
|
|
9067
9523
|
],
|
|
9068
9524
|
});
|
|
9069
9525
|
}
|
|
9526
|
+
if (filters.length > 0) {
|
|
9527
|
+
q = q.filterBy(
|
|
9528
|
+
filters.length === 1 ? filters[0] : { and: filters },
|
|
9529
|
+
);
|
|
9530
|
+
}
|
|
9070
9531
|
var orderBy = ["name"];
|
|
9071
9532
|
if (objectSlug === "account") orderBy.push("-ParentId");
|
|
9072
9533
|
return q
|
|
@@ -9129,7 +9590,12 @@
|
|
|
9129
9590
|
updateTriggerDisplay();
|
|
9130
9591
|
})
|
|
9131
9592
|
.catch(function () {
|
|
9132
|
-
selectedRecord = {
|
|
9593
|
+
selectedRecord = {
|
|
9594
|
+
id: value,
|
|
9595
|
+
value: value,
|
|
9596
|
+
name: value,
|
|
9597
|
+
label: value,
|
|
9598
|
+
};
|
|
9133
9599
|
updateTriggerDisplay();
|
|
9134
9600
|
});
|
|
9135
9601
|
}
|
|
@@ -9140,7 +9606,9 @@
|
|
|
9140
9606
|
loadWrap.className =
|
|
9141
9607
|
"flex flex-row items-center justify-center gap-8 py-12 px-12 w-full text-reg-12 text-typography-quaternary-text record-select-loading";
|
|
9142
9608
|
if (Spinner && typeof Spinner.create === "function") {
|
|
9143
|
-
loadWrap.appendChild(
|
|
9609
|
+
loadWrap.appendChild(
|
|
9610
|
+
Spinner.create({ size: "small", text: "Loading..." }),
|
|
9611
|
+
);
|
|
9144
9612
|
} else {
|
|
9145
9613
|
var loadText = document.createElement("span");
|
|
9146
9614
|
loadText.textContent = "Loading...";
|
|
@@ -9148,12 +9616,12 @@
|
|
|
9148
9616
|
}
|
|
9149
9617
|
optionsList.appendChild(loadWrap);
|
|
9150
9618
|
}
|
|
9151
|
-
|
|
9619
|
+
|
|
9152
9620
|
function showLoadingMore() {
|
|
9153
9621
|
// Remove existing loading more indicator
|
|
9154
9622
|
var existing = optionsList.querySelector(".record-select-loading-more");
|
|
9155
9623
|
if (existing) existing.remove();
|
|
9156
|
-
|
|
9624
|
+
|
|
9157
9625
|
var loadWrap = document.createElement("div");
|
|
9158
9626
|
loadWrap.className =
|
|
9159
9627
|
"flex flex-row items-center justify-center gap-8 py-8 px-12 w-full text-reg-12 text-typography-quaternary-text record-select-loading-more";
|
|
@@ -9166,9 +9634,11 @@
|
|
|
9166
9634
|
}
|
|
9167
9635
|
optionsList.appendChild(loadWrap);
|
|
9168
9636
|
}
|
|
9169
|
-
|
|
9637
|
+
|
|
9170
9638
|
function removeLoadingMore() {
|
|
9171
|
-
var loadingMore = optionsList.querySelector(
|
|
9639
|
+
var loadingMore = optionsList.querySelector(
|
|
9640
|
+
".record-select-loading-more",
|
|
9641
|
+
);
|
|
9172
9642
|
if (loadingMore) loadingMore.remove();
|
|
9173
9643
|
}
|
|
9174
9644
|
|
|
@@ -9187,13 +9657,15 @@
|
|
|
9187
9657
|
existingOptions.forEach(function (opt) {
|
|
9188
9658
|
opt.remove();
|
|
9189
9659
|
});
|
|
9190
|
-
|
|
9660
|
+
|
|
9191
9661
|
// Remove old loading/empty states
|
|
9192
|
-
var oldStates = optionsList.querySelectorAll(
|
|
9662
|
+
var oldStates = optionsList.querySelectorAll(
|
|
9663
|
+
".record-select-loading, .record-select-empty",
|
|
9664
|
+
);
|
|
9193
9665
|
oldStates.forEach(function (el) {
|
|
9194
9666
|
el.remove();
|
|
9195
9667
|
});
|
|
9196
|
-
|
|
9668
|
+
|
|
9197
9669
|
filteredRecords.forEach(function (rec) {
|
|
9198
9670
|
var optionValue = rec.id || rec.value;
|
|
9199
9671
|
var optionLabel = rec.name || rec.label || rec.value;
|
|
@@ -9208,7 +9680,7 @@
|
|
|
9208
9680
|
"hover:bg-fill-tertiary-fill-light-gray focus:bg-fill-tertiary-fill-light-gray",
|
|
9209
9681
|
isSelected
|
|
9210
9682
|
? "bg-primary-surface hover:!bg-primary-surface-hover"
|
|
9211
|
-
: ""
|
|
9683
|
+
: "",
|
|
9212
9684
|
);
|
|
9213
9685
|
|
|
9214
9686
|
var optContent = document.createElement("span");
|
|
@@ -9266,70 +9738,93 @@
|
|
|
9266
9738
|
|
|
9267
9739
|
optionsList.appendChild(option);
|
|
9268
9740
|
});
|
|
9269
|
-
|
|
9741
|
+
|
|
9270
9742
|
// Add loading more indicator at the bottom if fetching
|
|
9271
9743
|
if (isFetchingMore) {
|
|
9272
9744
|
showLoadingMore();
|
|
9273
9745
|
}
|
|
9274
9746
|
}
|
|
9275
9747
|
|
|
9748
|
+
function scheduleUpdatePosition() {
|
|
9749
|
+
if (popover && typeof popover.updatePosition === "function") {
|
|
9750
|
+
requestAnimationFrame(function () {
|
|
9751
|
+
requestAnimationFrame(function () {
|
|
9752
|
+
popover.updatePosition();
|
|
9753
|
+
});
|
|
9754
|
+
});
|
|
9755
|
+
}
|
|
9756
|
+
}
|
|
9757
|
+
|
|
9276
9758
|
function loadInitialAndRender() {
|
|
9277
9759
|
showLoading();
|
|
9278
9760
|
currentPage = 1;
|
|
9279
9761
|
hasMoreRecords = true;
|
|
9280
9762
|
totalFetched = 0;
|
|
9281
|
-
|
|
9282
|
-
fetchRecords(searchTerm, initialLimit, 1)
|
|
9283
|
-
|
|
9284
|
-
|
|
9285
|
-
|
|
9286
|
-
|
|
9287
|
-
|
|
9288
|
-
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9763
|
+
|
|
9764
|
+
fetchRecords(searchTerm, initialLimit, 1)
|
|
9765
|
+
.then(function (result) {
|
|
9766
|
+
allRecords = result.records;
|
|
9767
|
+
filteredRecords = result.records;
|
|
9768
|
+
hasMoreRecords = result.hasMore;
|
|
9769
|
+
totalFetched = result.records.length;
|
|
9770
|
+
currentPage = 1;
|
|
9771
|
+
|
|
9772
|
+
if (
|
|
9773
|
+
value &&
|
|
9774
|
+
!result.records.some(function (r) {
|
|
9775
|
+
return (r.id || r.value) === value;
|
|
9776
|
+
})
|
|
9777
|
+
) {
|
|
9778
|
+
loadSelectedRecord();
|
|
9779
|
+
} else if (value && result.records.length) {
|
|
9780
|
+
var sel = result.records.find(function (r) {
|
|
9781
|
+
return (r.id || r.value) === value;
|
|
9782
|
+
});
|
|
9783
|
+
if (sel) selectedRecord = sel;
|
|
9784
|
+
updateTriggerDisplay();
|
|
9785
|
+
}
|
|
9786
|
+
if (filteredRecords.length === 0) {
|
|
9787
|
+
showEmpty(searchTerm ? "No results found" : "No records available");
|
|
9788
|
+
} else {
|
|
9789
|
+
renderOptions();
|
|
9790
|
+
}
|
|
9791
|
+
scheduleUpdatePosition();
|
|
9792
|
+
})
|
|
9793
|
+
.catch(function () {
|
|
9794
|
+
showEmpty("Failed to load records");
|
|
9795
|
+
hasMoreRecords = false;
|
|
9796
|
+
scheduleUpdatePosition();
|
|
9797
|
+
});
|
|
9305
9798
|
}
|
|
9306
|
-
|
|
9799
|
+
|
|
9307
9800
|
function loadMoreRecords() {
|
|
9308
9801
|
if (isFetchingMore || !hasMoreRecords) return;
|
|
9309
|
-
|
|
9802
|
+
|
|
9310
9803
|
isFetchingMore = true;
|
|
9311
9804
|
currentPage += 1;
|
|
9312
9805
|
showLoadingMore();
|
|
9313
|
-
|
|
9314
|
-
fetchRecords(searchTerm, initialLimit, currentPage)
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9806
|
+
|
|
9807
|
+
fetchRecords(searchTerm, initialLimit, currentPage)
|
|
9808
|
+
.then(function (result) {
|
|
9809
|
+
isFetchingMore = false;
|
|
9810
|
+
removeLoadingMore();
|
|
9811
|
+
|
|
9812
|
+
if (result.records.length > 0) {
|
|
9813
|
+
allRecords = allRecords.concat(result.records);
|
|
9814
|
+
filteredRecords = filteredRecords.concat(result.records);
|
|
9815
|
+
totalFetched += result.records.length;
|
|
9816
|
+
hasMoreRecords = result.hasMore;
|
|
9817
|
+
renderOptions();
|
|
9818
|
+
} else {
|
|
9819
|
+
hasMoreRecords = false;
|
|
9820
|
+
}
|
|
9821
|
+
})
|
|
9822
|
+
.catch(function (err) {
|
|
9823
|
+
console.error("[RecordSelect] loadMoreRecords error:", err);
|
|
9824
|
+
isFetchingMore = false;
|
|
9825
|
+
removeLoadingMore();
|
|
9325
9826
|
hasMoreRecords = false;
|
|
9326
|
-
}
|
|
9327
|
-
}).catch(function (err) {
|
|
9328
|
-
console.error("[RecordSelect] loadMoreRecords error:", err);
|
|
9329
|
-
isFetchingMore = false;
|
|
9330
|
-
removeLoadingMore();
|
|
9331
|
-
hasMoreRecords = false;
|
|
9332
|
-
});
|
|
9827
|
+
});
|
|
9333
9828
|
}
|
|
9334
9829
|
|
|
9335
9830
|
function debouncedSearch() {
|
|
@@ -9340,22 +9835,26 @@
|
|
|
9340
9835
|
currentPage = 1;
|
|
9341
9836
|
hasMoreRecords = true;
|
|
9342
9837
|
totalFetched = 0;
|
|
9343
|
-
|
|
9344
|
-
fetchRecords(searchTerm, initialLimit, 1)
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9838
|
+
|
|
9839
|
+
fetchRecords(searchTerm, initialLimit, 1)
|
|
9840
|
+
.then(function (result) {
|
|
9841
|
+
allRecords = result.records;
|
|
9842
|
+
filteredRecords = result.records;
|
|
9843
|
+
hasMoreRecords = result.hasMore;
|
|
9844
|
+
totalFetched = result.records.length;
|
|
9845
|
+
|
|
9846
|
+
if (result.records.length === 0) {
|
|
9847
|
+
showEmpty("No results found");
|
|
9848
|
+
} else {
|
|
9849
|
+
renderOptions();
|
|
9850
|
+
}
|
|
9851
|
+
scheduleUpdatePosition();
|
|
9852
|
+
})
|
|
9853
|
+
.catch(function () {
|
|
9854
|
+
showEmpty("Search failed");
|
|
9855
|
+
hasMoreRecords = false;
|
|
9856
|
+
scheduleUpdatePosition();
|
|
9857
|
+
});
|
|
9359
9858
|
}, 500);
|
|
9360
9859
|
}
|
|
9361
9860
|
|
|
@@ -9400,7 +9899,7 @@
|
|
|
9400
9899
|
size,
|
|
9401
9900
|
disabled,
|
|
9402
9901
|
!value,
|
|
9403
|
-
canClear && !!value && !disabled
|
|
9902
|
+
canClear && !!value && !disabled,
|
|
9404
9903
|
);
|
|
9405
9904
|
if (disabled && isOpen) closeDropdown();
|
|
9406
9905
|
};
|
|
@@ -9419,7 +9918,7 @@
|
|
|
9419
9918
|
|
|
9420
9919
|
|
|
9421
9920
|
// ============================================
|
|
9422
|
-
// File 18/
|
|
9921
|
+
// File 18/42: components/multiselect.js
|
|
9423
9922
|
// ============================================
|
|
9424
9923
|
|
|
9425
9924
|
/**
|
|
@@ -9577,11 +10076,11 @@
|
|
|
9577
10076
|
var content = document.createElement("div");
|
|
9578
10077
|
content.setAttribute("role", "listbox");
|
|
9579
10078
|
content.setAttribute("aria-multiselectable", "true");
|
|
9580
|
-
content.className = "custom-multiselect-content w-full max-h-[
|
|
10079
|
+
content.className = "custom-multiselect-content w-full max-h-[45vh] overflow-hidden flex flex-col";
|
|
9581
10080
|
|
|
9582
10081
|
var optionsList = document.createElement("div");
|
|
9583
10082
|
optionsList.className =
|
|
9584
|
-
"overflow-y-auto max-h-[
|
|
10083
|
+
"overflow-y-auto max-h-[45vh] p-2 w-full rounded-4 bg-fill-quarternary-fill-white";
|
|
9585
10084
|
|
|
9586
10085
|
function isSelected(optionValue) {
|
|
9587
10086
|
return values.some(function (v) {
|
|
@@ -9686,7 +10185,7 @@
|
|
|
9686
10185
|
align: "start",
|
|
9687
10186
|
closeOnClickOutside: true,
|
|
9688
10187
|
bodyClassName: "p-0 overflow-hidden",
|
|
9689
|
-
panelClassName: "min-w-[var(--trigger-width)] max-h-[
|
|
10188
|
+
panelClassName: "min-w-[var(--trigger-width)] max-h-[45vh] overflow-hidden",
|
|
9690
10189
|
onOpen: function () {
|
|
9691
10190
|
if (disabled) {
|
|
9692
10191
|
popover.hide();
|
|
@@ -9800,7 +10299,7 @@
|
|
|
9800
10299
|
|
|
9801
10300
|
|
|
9802
10301
|
// ============================================
|
|
9803
|
-
// File 19/
|
|
10302
|
+
// File 19/42: components/enum-multiselect.js
|
|
9804
10303
|
// ============================================
|
|
9805
10304
|
|
|
9806
10305
|
/**
|
|
@@ -10061,7 +10560,7 @@
|
|
|
10061
10560
|
var content = document.createElement("div");
|
|
10062
10561
|
content.setAttribute("role", "listbox");
|
|
10063
10562
|
content.setAttribute("aria-multiselectable", "true");
|
|
10064
|
-
content.className = "w-full min-w-[200px] max-h-[
|
|
10563
|
+
content.className = "w-full min-w-[200px] max-h-[45vh] overflow-hidden flex flex-col";
|
|
10065
10564
|
|
|
10066
10565
|
// Search input (using InputComponent like enum-select)
|
|
10067
10566
|
var searchContainer = document.createElement("div");
|
|
@@ -10122,7 +10621,7 @@
|
|
|
10122
10621
|
// Options list
|
|
10123
10622
|
var optionsList = document.createElement("div");
|
|
10124
10623
|
optionsList.className =
|
|
10125
|
-
"overflow-y-auto max-h-[
|
|
10624
|
+
"overflow-y-auto max-h-[45vh] p-2 w-full rounded-4 bg-fill-quarternary-fill-white flex-1 min-h-0";
|
|
10126
10625
|
|
|
10127
10626
|
content.appendChild(searchContainer);
|
|
10128
10627
|
content.appendChild(optionsList);
|
|
@@ -10624,7 +11123,7 @@
|
|
|
10624
11123
|
|
|
10625
11124
|
|
|
10626
11125
|
// ============================================
|
|
10627
|
-
// File 20/
|
|
11126
|
+
// File 20/42: components/record-multiselect.js
|
|
10628
11127
|
// ============================================
|
|
10629
11128
|
|
|
10630
11129
|
/**
|
|
@@ -10780,6 +11279,7 @@
|
|
|
10780
11279
|
* @param {string} [config.size] - 'default' | 'large' | 'small'
|
|
10781
11280
|
* @param {number} [config.initialLimit] - Initial fetch limit (default 50)
|
|
10782
11281
|
* @param {Array<string>} [config.displayFields] - Fields to display as secondary info (e.g. ["email", "phone"])
|
|
11282
|
+
* @param {Object} [config.initialFilter] - Optional filter object to merge with search (e.g. { field: "status", operator: "exact", value: "active" } or { and: [...] })
|
|
10783
11283
|
* @param {Object} [config.objectSchema] - Optional object type/schema; properties.icon_data { icon?, color? } used for static icon (not used for user; user shows Vivid Avatar)
|
|
10784
11284
|
* @returns {HTMLElement} Record multiselect container element
|
|
10785
11285
|
*/
|
|
@@ -10794,6 +11294,7 @@
|
|
|
10794
11294
|
var variant = config.variant || "default";
|
|
10795
11295
|
var size = config.size || "default";
|
|
10796
11296
|
var initialLimit = config.initialLimit != null ? config.initialLimit : 50;
|
|
11297
|
+
var initialFilter = config.initialFilter || null; // Can be array, object, or function returning either
|
|
10797
11298
|
var displayFields = config.displayFields || [];
|
|
10798
11299
|
|
|
10799
11300
|
var disabled = config.disabled === true;
|
|
@@ -10919,7 +11420,7 @@
|
|
|
10919
11420
|
var content = document.createElement("div");
|
|
10920
11421
|
content.setAttribute("role", "listbox");
|
|
10921
11422
|
content.setAttribute("aria-multiselectable", "true");
|
|
10922
|
-
content.className = "record-multiselect-content max-h-[
|
|
11423
|
+
content.className = "record-multiselect-content max-h-[45vh] overflow-hidden flex flex-col";
|
|
10923
11424
|
|
|
10924
11425
|
var searchWrap = document.createElement("div");
|
|
10925
11426
|
searchWrap.className = "p-8 pb-4 border-b-1/2 border-border-primary ";
|
|
@@ -10969,7 +11470,7 @@
|
|
|
10969
11470
|
content.appendChild(searchWrap);
|
|
10970
11471
|
|
|
10971
11472
|
var optionsList = document.createElement("div");
|
|
10972
|
-
optionsList.className = "overflow-y-auto max-h-[
|
|
11473
|
+
optionsList.className = "overflow-y-auto max-h-[45vh] p-2 w-full rounded-4 bg-fill-quarternary-fill-white record-multiselect-options";
|
|
10973
11474
|
|
|
10974
11475
|
// Add scroll listener for infinite scroll
|
|
10975
11476
|
optionsList.addEventListener("scroll", function () {
|
|
@@ -10997,28 +11498,22 @@
|
|
|
10997
11498
|
align: "start",
|
|
10998
11499
|
closeOnClickOutside: true,
|
|
10999
11500
|
bodyClassName: "p-0 overflow-hidden",
|
|
11000
|
-
panelClassName: "
|
|
11501
|
+
panelClassName: "min-w-[var(--trigger-width)] overflow-hidden",
|
|
11001
11502
|
onOpen: function () {
|
|
11002
11503
|
if (disabled) {
|
|
11003
11504
|
popover.hide();
|
|
11004
11505
|
return;
|
|
11005
11506
|
}
|
|
11006
|
-
document.querySelectorAll(".custom-select.open, .record-select.open, .custom-multiselect.open, .record-multiselect.open, .enum-select, .enum-multiselect").forEach(function (other) {
|
|
11007
|
-
if (other !== container && other.popoverInstance) {
|
|
11008
|
-
other.popoverInstance.hide();
|
|
11009
|
-
}
|
|
11010
|
-
});
|
|
11011
11507
|
container.classList.add("open");
|
|
11012
11508
|
trigger.setAttribute("aria-expanded", "true");
|
|
11013
11509
|
searchTerm = "";
|
|
11014
11510
|
if (searchInputWrapper) searchInputWrapper.setValue("");
|
|
11015
11511
|
else if (searchInputEl) searchInputEl.value = "";
|
|
11016
|
-
var triggerWidthPx = trigger.offsetWidth + "px";
|
|
11017
|
-
content.style.minWidth = triggerWidthPx;
|
|
11018
|
-
content.style.width = triggerWidthPx;
|
|
11019
11512
|
if (popover.panel) {
|
|
11020
|
-
|
|
11513
|
+
var triggerWidthPx = trigger.offsetWidth + "px";
|
|
11514
|
+
popover.panel.style.setProperty("--trigger-width", triggerWidthPx);
|
|
11021
11515
|
popover.panel.style.minWidth = triggerWidthPx;
|
|
11516
|
+
popover.panel.style.width = triggerWidthPx;
|
|
11022
11517
|
}
|
|
11023
11518
|
loadInitialAndRender();
|
|
11024
11519
|
setTimeout(function () {
|
|
@@ -11097,14 +11592,23 @@
|
|
|
11097
11592
|
try {
|
|
11098
11593
|
if (model && typeof model.select === "function") {
|
|
11099
11594
|
var q = model.select.apply(model, fields);
|
|
11595
|
+
var filters = [];
|
|
11596
|
+
var resolvedFilter = typeof initialFilter === 'function' ? initialFilter() : initialFilter;
|
|
11597
|
+
console.log('[RecordMultiselect] initialFilter:', resolvedFilter, '| search:', search);
|
|
11598
|
+
if (resolvedFilter) {
|
|
11599
|
+
filters = filters.concat(Array.isArray(resolvedFilter) ? resolvedFilter : [resolvedFilter]);
|
|
11600
|
+
}
|
|
11100
11601
|
if (search && search.trim()) {
|
|
11101
|
-
|
|
11602
|
+
filters.push({
|
|
11102
11603
|
or: [
|
|
11103
11604
|
{ field: "name", operator: "contains", value: search.trim() },
|
|
11104
11605
|
{ field: "id", operator: "eq", value: search.trim() },
|
|
11105
11606
|
],
|
|
11106
11607
|
});
|
|
11107
11608
|
}
|
|
11609
|
+
if (filters.length > 0) {
|
|
11610
|
+
q = q.filterBy(filters.length === 1 ? filters[0] : { and: filters });
|
|
11611
|
+
}
|
|
11108
11612
|
var orderBy = ["name"];
|
|
11109
11613
|
if (objectSlug === "account") orderBy.push("-ParentId");
|
|
11110
11614
|
return q
|
|
@@ -11363,6 +11867,16 @@
|
|
|
11363
11867
|
}
|
|
11364
11868
|
}
|
|
11365
11869
|
|
|
11870
|
+
function scheduleUpdatePosition() {
|
|
11871
|
+
if (popover && typeof popover.updatePosition === "function") {
|
|
11872
|
+
requestAnimationFrame(function () {
|
|
11873
|
+
requestAnimationFrame(function () {
|
|
11874
|
+
popover.updatePosition();
|
|
11875
|
+
});
|
|
11876
|
+
});
|
|
11877
|
+
}
|
|
11878
|
+
}
|
|
11879
|
+
|
|
11366
11880
|
function loadInitialAndRender() {
|
|
11367
11881
|
showLoading();
|
|
11368
11882
|
currentPage = 1;
|
|
@@ -11381,9 +11895,11 @@
|
|
|
11381
11895
|
} else {
|
|
11382
11896
|
renderOptions();
|
|
11383
11897
|
}
|
|
11898
|
+
scheduleUpdatePosition();
|
|
11384
11899
|
}).catch(function () {
|
|
11385
11900
|
showEmpty("Failed to load records");
|
|
11386
11901
|
hasMoreRecords = false;
|
|
11902
|
+
scheduleUpdatePosition();
|
|
11387
11903
|
});
|
|
11388
11904
|
}
|
|
11389
11905
|
|
|
@@ -11435,9 +11951,11 @@
|
|
|
11435
11951
|
} else {
|
|
11436
11952
|
renderOptions();
|
|
11437
11953
|
}
|
|
11954
|
+
scheduleUpdatePosition();
|
|
11438
11955
|
}).catch(function () {
|
|
11439
11956
|
showEmpty("Search failed");
|
|
11440
11957
|
hasMoreRecords = false;
|
|
11958
|
+
scheduleUpdatePosition();
|
|
11441
11959
|
});
|
|
11442
11960
|
}, 500);
|
|
11443
11961
|
}
|
|
@@ -11507,7 +12025,7 @@
|
|
|
11507
12025
|
|
|
11508
12026
|
|
|
11509
12027
|
// ============================================
|
|
11510
|
-
// File 21/
|
|
12028
|
+
// File 21/42: components/input.js
|
|
11511
12029
|
// ============================================
|
|
11512
12030
|
|
|
11513
12031
|
/**
|
|
@@ -11534,7 +12052,7 @@
|
|
|
11534
12052
|
|
|
11535
12053
|
var WRAPPER_CLASS = {
|
|
11536
12054
|
base:
|
|
11537
|
-
"group flex items-center border-1/2 border-border-primary rounded-4 text-typography-primary-text gap-x-8 w-full transition-all ease-in-out",
|
|
12055
|
+
"group flex items-center border-1/2 border-border-primary rounded-4 text-typography-primary-text gap-x-8 w-full transition-all ease-in-out group-has-[:disabled]:cursor-not-allowed group-has-[:disabled]:border-border-primary group-has-[:disabled]:bg-fill-tertiary-fill-light-gray group-has-[:disabled]:text-typography-quaternary-text group-has-[:disabled]:hover:border-border-primary group-has-[:disabled]:[&_input]:cursor-not-allowed group-has-[:disabled]:[&_input]:text-typography-quaternary-text",
|
|
11538
12056
|
default:
|
|
11539
12057
|
"bg-fill-quarternary-fill-white hover:border-primary-base focus-within:border-primary-base",
|
|
11540
12058
|
error:
|
|
@@ -11609,13 +12127,16 @@
|
|
|
11609
12127
|
var isPassword = type === "password";
|
|
11610
12128
|
|
|
11611
12129
|
var wrapper = document.createElement("div");
|
|
11612
|
-
|
|
11613
|
-
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
|
|
11617
|
-
|
|
11618
|
-
|
|
12130
|
+
var sizeClass = inputSize === "large" ? WRAPPER_CLASS.sizeLarge : inputSize === "small" ? WRAPPER_CLASS.sizeSmall : WRAPPER_CLASS.sizeDefault;
|
|
12131
|
+
function applyWrapperClasses() {
|
|
12132
|
+
wrapper.className = join(
|
|
12133
|
+
WRAPPER_CLASS.base,
|
|
12134
|
+
disabled ? WRAPPER_CLASS.disabled : (WRAPPER_CLASS[variant] || WRAPPER_CLASS.default),
|
|
12135
|
+
sizeClass,
|
|
12136
|
+
config.className || ""
|
|
12137
|
+
);
|
|
12138
|
+
}
|
|
12139
|
+
applyWrapperClasses();
|
|
11619
12140
|
wrapper.setAttribute("data-input-variant", variant);
|
|
11620
12141
|
|
|
11621
12142
|
if (config.prefixNode) {
|
|
@@ -11745,19 +12266,12 @@
|
|
|
11745
12266
|
wrapper.setVariant = function (v) {
|
|
11746
12267
|
variant = v;
|
|
11747
12268
|
wrapper.setAttribute("data-input-variant", v);
|
|
11748
|
-
|
|
11749
|
-
WRAPPER_CLASS.base,
|
|
11750
|
-
WRAPPER_CLASS[variant] || WRAPPER_CLASS.default,
|
|
11751
|
-
inputSize === "large" ? WRAPPER_CLASS.sizeLarge : inputSize === "small" ? WRAPPER_CLASS.sizeSmall : WRAPPER_CLASS.sizeDefault,
|
|
11752
|
-
disabled ? WRAPPER_CLASS.disabled : "",
|
|
11753
|
-
config.className || ""
|
|
11754
|
-
);
|
|
12269
|
+
applyWrapperClasses();
|
|
11755
12270
|
};
|
|
11756
12271
|
wrapper.setDisabled = function (d) {
|
|
11757
12272
|
disabled = !!d;
|
|
11758
12273
|
input.disabled = disabled;
|
|
11759
|
-
|
|
11760
|
-
wrapper.classList.toggle("opacity-60", disabled);
|
|
12274
|
+
applyWrapperClasses();
|
|
11761
12275
|
};
|
|
11762
12276
|
|
|
11763
12277
|
return wrapper;
|
|
@@ -11772,7 +12286,7 @@
|
|
|
11772
12286
|
|
|
11773
12287
|
|
|
11774
12288
|
// ============================================
|
|
11775
|
-
// File 22/
|
|
12289
|
+
// File 22/42: components/currency.js
|
|
11776
12290
|
// ============================================
|
|
11777
12291
|
|
|
11778
12292
|
/**
|
|
@@ -11802,7 +12316,7 @@
|
|
|
11802
12316
|
sizeLarge: "",
|
|
11803
12317
|
sizeSmall: "",
|
|
11804
12318
|
disabled:
|
|
11805
|
-
"cursor-not-allowed border-border-primary bg-fill-tertiary-fill-light-gray text-typography-quaternary-text hover:border-border-primary",
|
|
12319
|
+
"pointer-events-none cursor-not-allowed border-border-primary bg-fill-tertiary-fill-light-gray text-typography-quaternary-text hover:border-border-primary",
|
|
11806
12320
|
};
|
|
11807
12321
|
|
|
11808
12322
|
// Currency type label: fit-content, separator (border-r) on type only, full height
|
|
@@ -11989,7 +12503,12 @@
|
|
|
11989
12503
|
wrapper.setDisabled = function (d) {
|
|
11990
12504
|
disabled = !!d;
|
|
11991
12505
|
input.disabled = disabled;
|
|
11992
|
-
wrapper.
|
|
12506
|
+
wrapper.className = join(
|
|
12507
|
+
WRAPPER_CLASS.base,
|
|
12508
|
+
WRAPPER_CLASS[variant] != null ? WRAPPER_CLASS[variant] : WRAPPER_CLASS.default,
|
|
12509
|
+
disabled ? WRAPPER_CLASS.disabled : "",
|
|
12510
|
+
config.className || ""
|
|
12511
|
+
);
|
|
11993
12512
|
};
|
|
11994
12513
|
|
|
11995
12514
|
return wrapper;
|
|
@@ -12005,7 +12524,7 @@
|
|
|
12005
12524
|
|
|
12006
12525
|
|
|
12007
12526
|
// ============================================
|
|
12008
|
-
// File 23/
|
|
12527
|
+
// File 23/42: components/textarea.js
|
|
12009
12528
|
// ============================================
|
|
12010
12529
|
|
|
12011
12530
|
/**
|
|
@@ -12030,7 +12549,7 @@
|
|
|
12030
12549
|
warning:
|
|
12031
12550
|
"min-h-[80px] border-warning-base hover:border-warning-base focus:border-warning-base",
|
|
12032
12551
|
disabled:
|
|
12033
|
-
"cursor-not-allowed border-border-primary bg-fill-tertiary-fill-light-gray text-typography-quaternary-text hover:border-border-primary",
|
|
12552
|
+
"pointer-events-none cursor-not-allowed border-border-primary bg-fill-tertiary-fill-light-gray text-typography-quaternary-text hover:border-border-primary",
|
|
12034
12553
|
};
|
|
12035
12554
|
|
|
12036
12555
|
function join() {
|
|
@@ -12125,7 +12644,347 @@
|
|
|
12125
12644
|
|
|
12126
12645
|
|
|
12127
12646
|
// ============================================
|
|
12128
|
-
// File 24/
|
|
12647
|
+
// File 24/42: components/richtext-editor.js
|
|
12648
|
+
// ============================================
|
|
12649
|
+
|
|
12650
|
+
/**
|
|
12651
|
+
* Rich Text Editor Component (vanilla JS)
|
|
12652
|
+
* Toolbar + contenteditable area with formatting (bold, italic, underline, headings, lists, alignment, link, image, code block, undo/redo).
|
|
12653
|
+
* Styling matches design: rounded-12, toolbar bg-fill-tertiary-fill-light-gray, content area with min-height.
|
|
12654
|
+
*/
|
|
12655
|
+
|
|
12656
|
+
(function (global) {
|
|
12657
|
+
|
|
12658
|
+
var RICH_TEXT_CONTENT_STYLES =
|
|
12659
|
+
".rich-text-editor-content ul{list-style-type:disc;padding-left:1.5em;margin:0.5em 0}" +
|
|
12660
|
+
".rich-text-editor-content ol{list-style-type:decimal;padding-left:1.5em;margin:0.5em 0}" +
|
|
12661
|
+
".rich-text-editor-content li{margin:0.25em 0}" +
|
|
12662
|
+
".rich-text-editor-content li p{margin:0}" +
|
|
12663
|
+
".rich-text-editor-content h1{font-size:1.5rem;font-weight:700;line-height:1.3;margin:0.75em 0 0.5em}" +
|
|
12664
|
+
".rich-text-editor-content h2{font-size:1.25rem;font-weight:600;line-height:1.3;margin:0.75em 0 0.5em}" +
|
|
12665
|
+
".rich-text-editor-content h3{font-size:1.125rem;font-weight:600;line-height:1.3;margin:0.75em 0 0.5em}" +
|
|
12666
|
+
".rich-text-editor-content p{margin:0.5em 0}" +
|
|
12667
|
+
".rich-text-editor-content a{color:var(--color-primary-500);text-decoration:underline;cursor:pointer}" +
|
|
12668
|
+
".rich-text-editor-content pre{background:var(--color-neutral-100);border-radius:var(--sizes-size-8);padding:0.75em 1em;margin:0.5em 0;overflow-x:auto}" +
|
|
12669
|
+
".rich-text-editor-content code{font-family:ui-monospace,monospace;font-size:0.875em}" +
|
|
12670
|
+
".rich-text-editor-content img{max-width:100%;height:auto;margin:0.5em 0}" +
|
|
12671
|
+
".rich-text-editor-content blockquote{border-left:3px solid var(--color-neutral-200);padding-left:1em;margin:0.5em 0;color:var(--color-neutral-600)}" +
|
|
12672
|
+
".rich-text-editor-content hr{border:none;border-top:1px solid var(--color-neutral-150);margin:1em 0}" +
|
|
12673
|
+
".rich-text-editor-content .ProseMirror,.rich-text-editor-content [contenteditable]{outline:none}";
|
|
12674
|
+
|
|
12675
|
+
function join() {
|
|
12676
|
+
return Array.prototype.filter.call(arguments, Boolean).join(" ");
|
|
12677
|
+
}
|
|
12678
|
+
|
|
12679
|
+
function getDep(name) {
|
|
12680
|
+
if (typeof global.FlowUI !== "undefined" && typeof global.FlowUI._getComponent === "function") {
|
|
12681
|
+
var c = global.FlowUI._getComponent(name);
|
|
12682
|
+
if (c) return c;
|
|
12683
|
+
}
|
|
12684
|
+
return global[name];
|
|
12685
|
+
}
|
|
12686
|
+
|
|
12687
|
+
/** Get Tabler icon element (16px) from Icon component for toolbar. */
|
|
12688
|
+
function getTablerIcon(iconName) {
|
|
12689
|
+
var Icon = getDep("Icon");
|
|
12690
|
+
if (!Icon || !Icon.iconMap || !Icon.iconMap[iconName]) return null;
|
|
12691
|
+
var svgStr = Icon.iconMap[iconName];
|
|
12692
|
+
var s16 = svgStr.replace(/width="24"/, 'width="16"').replace(/height="24"/, 'height="16"').replace(/width="20"/, 'width="16"').replace(/height="20"/, 'height="16"');
|
|
12693
|
+
var span = document.createElement("span");
|
|
12694
|
+
span.className = "flex items-center justify-center size-16";
|
|
12695
|
+
span.innerHTML = s16;
|
|
12696
|
+
return span;
|
|
12697
|
+
}
|
|
12698
|
+
|
|
12699
|
+
function createToolbarButton(opts) {
|
|
12700
|
+
var Button = getDep("Button");
|
|
12701
|
+
if (!Button || typeof Button.create !== "function") {
|
|
12702
|
+
throw new Error("RichTextEditor requires Button");
|
|
12703
|
+
}
|
|
12704
|
+
var icon = opts.iconStr ? getTablerIcon(opts.iconStr) : null;
|
|
12705
|
+
return Button.create({
|
|
12706
|
+
variant: "outline",
|
|
12707
|
+
size: "default",
|
|
12708
|
+
title: opts.title,
|
|
12709
|
+
icon: icon,
|
|
12710
|
+
onClick: opts.onClick,
|
|
12711
|
+
disabled: opts.disabled,
|
|
12712
|
+
});
|
|
12713
|
+
}
|
|
12714
|
+
|
|
12715
|
+
function createSeparator() {
|
|
12716
|
+
var sep = document.createElement("div");
|
|
12717
|
+
sep.className = "w-px h-16 bg-border-primary mx-4";
|
|
12718
|
+
sep.setAttribute("aria-hidden", "true");
|
|
12719
|
+
return sep;
|
|
12720
|
+
}
|
|
12721
|
+
|
|
12722
|
+
/**
|
|
12723
|
+
* Create a rich text editor
|
|
12724
|
+
* @param {Object} config
|
|
12725
|
+
* @param {string} [config.value] - Initial HTML content
|
|
12726
|
+
* @param {string} [config.placeholder] - Placeholder when empty
|
|
12727
|
+
* @param {number} [config.minHeightPx] - Min height of editor area (default 400)
|
|
12728
|
+
* @param {boolean} [config.disabled]
|
|
12729
|
+
* @param {Function} [config.onChange] - (html: string) => void
|
|
12730
|
+
* @returns {HTMLElement} Wrapper element with getValue/setValue/setDisabled/getInput
|
|
12731
|
+
*/
|
|
12732
|
+
function create(config) {
|
|
12733
|
+
var value = config.value != null ? String(config.value) : "";
|
|
12734
|
+
var placeholder = config.placeholder != null ? config.placeholder : "";
|
|
12735
|
+
var minHeightPx = config.minHeightPx != null ? config.minHeightPx : 400;
|
|
12736
|
+
var disabled = !!config.disabled;
|
|
12737
|
+
var onChange = config.onChange;
|
|
12738
|
+
|
|
12739
|
+
var wrapper = document.createElement("div");
|
|
12740
|
+
wrapper.className = "w-full rounded-12 border border-borderColor-border-primary shadow-soft-2x-small";
|
|
12741
|
+
|
|
12742
|
+
var styleEl = document.createElement("style");
|
|
12743
|
+
styleEl.textContent = RICH_TEXT_CONTENT_STYLES;
|
|
12744
|
+
wrapper.appendChild(styleEl);
|
|
12745
|
+
|
|
12746
|
+
var toolbar = document.createElement("div");
|
|
12747
|
+
toolbar.className =
|
|
12748
|
+
"flex flex-wrap gap-4 rounded-t-12 border-borderColor-border-primary bg-fill-tertiary-fill-light-gray p-6";
|
|
12749
|
+
toolbar.setAttribute("role", "toolbar");
|
|
12750
|
+
|
|
12751
|
+
var editorEl = document.createElement("div");
|
|
12752
|
+
editorEl.contentEditable = !disabled;
|
|
12753
|
+
editorEl.className = join(
|
|
12754
|
+
"rich-text-editor-content max-w-none rounded-b-12 border-t border-borderColor-border-primary p-8 text-reg-14 text-typography-primary-text"
|
|
12755
|
+
);
|
|
12756
|
+
editorEl.style.minHeight = minHeightPx + "px";
|
|
12757
|
+
if (value) editorEl.innerHTML = value;
|
|
12758
|
+
editorEl.setAttribute("data-placeholder", placeholder);
|
|
12759
|
+
|
|
12760
|
+
function isEmpty() {
|
|
12761
|
+
var text = (editorEl.textContent || "").trim();
|
|
12762
|
+
if (text) return false;
|
|
12763
|
+
var html = (editorEl.innerHTML || "").replace(/<br\s*\/?>/gi, "\n").replace(/<[^>]+>/g, "");
|
|
12764
|
+
return !html.trim();
|
|
12765
|
+
}
|
|
12766
|
+
function updatePlaceholder() {
|
|
12767
|
+
if (placeholder && isEmpty()) {
|
|
12768
|
+
editorEl.classList.add("empty");
|
|
12769
|
+
editorEl.setAttribute("data-placeholder", placeholder);
|
|
12770
|
+
} else {
|
|
12771
|
+
editorEl.classList.remove("empty");
|
|
12772
|
+
editorEl.removeAttribute("data-placeholder");
|
|
12773
|
+
}
|
|
12774
|
+
}
|
|
12775
|
+
updatePlaceholder();
|
|
12776
|
+
|
|
12777
|
+
function getHtml() {
|
|
12778
|
+
return editorEl.innerHTML;
|
|
12779
|
+
}
|
|
12780
|
+
function setHtml(html) {
|
|
12781
|
+
editorEl.innerHTML = html || "";
|
|
12782
|
+
updatePlaceholder();
|
|
12783
|
+
}
|
|
12784
|
+
function notifyChange() {
|
|
12785
|
+
if (typeof onChange === "function") onChange(getHtml());
|
|
12786
|
+
}
|
|
12787
|
+
|
|
12788
|
+
function isActive(cmd, val) {
|
|
12789
|
+
try {
|
|
12790
|
+
return document.queryCommandState(cmd);
|
|
12791
|
+
} catch (e) {
|
|
12792
|
+
return false;
|
|
12793
|
+
}
|
|
12794
|
+
}
|
|
12795
|
+
function blockTag() {
|
|
12796
|
+
var sel = window.getSelection();
|
|
12797
|
+
if (!sel || sel.rangeCount === 0) return null;
|
|
12798
|
+
var node = sel.anchorNode;
|
|
12799
|
+
while (node && node !== editorEl) {
|
|
12800
|
+
if (node.nodeType === 1) {
|
|
12801
|
+
var n = node.nodeName.toLowerCase();
|
|
12802
|
+
if (["h1", "h2", "h3", "p", "div", "pre", "blockquote"].indexOf(n) !== -1) return n;
|
|
12803
|
+
}
|
|
12804
|
+
node = node.parentNode;
|
|
12805
|
+
}
|
|
12806
|
+
return null;
|
|
12807
|
+
}
|
|
12808
|
+
function isAlignment(align) {
|
|
12809
|
+
try {
|
|
12810
|
+
if (align === "left") return document.queryCommandState("justifyLeft");
|
|
12811
|
+
if (align === "center") return document.queryCommandState("justifyCenter");
|
|
12812
|
+
if (align === "right") return document.queryCommandState("justifyRight");
|
|
12813
|
+
} catch (e) {}
|
|
12814
|
+
return false;
|
|
12815
|
+
}
|
|
12816
|
+
|
|
12817
|
+
function refreshToolbar() {
|
|
12818
|
+
toolbar.querySelectorAll("button").forEach(function (btn) {
|
|
12819
|
+
var cmd = btn.getAttribute("data-command");
|
|
12820
|
+
var val = btn.getAttribute("data-value");
|
|
12821
|
+
if (!cmd) return;
|
|
12822
|
+
var active = false;
|
|
12823
|
+
if (cmd === "formatBlock") active = blockTag() === val;
|
|
12824
|
+
else if (cmd === "justifyLeft" && val === "left") active = isAlignment("left");
|
|
12825
|
+
else if (cmd === "justifyCenter" && val === "center") active = isAlignment("center");
|
|
12826
|
+
else if (cmd === "justifyRight" && val === "right") active = isAlignment("right");
|
|
12827
|
+
else active = isActive(cmd);
|
|
12828
|
+
btn.classList.toggle("bg-primary-base", active);
|
|
12829
|
+
btn.classList.toggle("border-primary-base", active);
|
|
12830
|
+
btn.classList.toggle("text-typography-invert-text", active);
|
|
12831
|
+
btn.classList.toggle("bg-fill-quarternary-fill-white", !active);
|
|
12832
|
+
btn.classList.toggle("border-border-primary", !active);
|
|
12833
|
+
btn.classList.toggle("text-typography-primary-text", !active);
|
|
12834
|
+
});
|
|
12835
|
+
}
|
|
12836
|
+
|
|
12837
|
+
function exec(cmd, value) {
|
|
12838
|
+
editorEl.focus();
|
|
12839
|
+
document.execCommand(cmd, false, value != null ? value : null);
|
|
12840
|
+
refreshToolbar();
|
|
12841
|
+
notifyChange();
|
|
12842
|
+
}
|
|
12843
|
+
|
|
12844
|
+
function insertCodeBlock() {
|
|
12845
|
+
editorEl.focus();
|
|
12846
|
+
var sel = window.getSelection();
|
|
12847
|
+
if (sel && sel.rangeCount) {
|
|
12848
|
+
var range = sel.getRangeAt(0);
|
|
12849
|
+
var pre = document.createElement("pre");
|
|
12850
|
+
var code = document.createElement("code");
|
|
12851
|
+
code.textContent = "code here";
|
|
12852
|
+
pre.appendChild(code);
|
|
12853
|
+
range.insertNode(pre);
|
|
12854
|
+
range.setStart(code, 0);
|
|
12855
|
+
range.setEnd(code, 0);
|
|
12856
|
+
sel.removeAllRanges();
|
|
12857
|
+
sel.addRange(range);
|
|
12858
|
+
}
|
|
12859
|
+
refreshToolbar();
|
|
12860
|
+
notifyChange();
|
|
12861
|
+
}
|
|
12862
|
+
|
|
12863
|
+
function addLink() {
|
|
12864
|
+
var url = window.prompt("Enter the URL:", "https://");
|
|
12865
|
+
if (url) {
|
|
12866
|
+
exec("createLink", url);
|
|
12867
|
+
}
|
|
12868
|
+
}
|
|
12869
|
+
|
|
12870
|
+
function addImage() {
|
|
12871
|
+
var input = document.createElement("input");
|
|
12872
|
+
input.type = "file";
|
|
12873
|
+
input.accept = "image/*";
|
|
12874
|
+
input.onchange = function (e) {
|
|
12875
|
+
var file = e.target && e.target.files && e.target.files[0];
|
|
12876
|
+
if (file) {
|
|
12877
|
+
var reader = new FileReader();
|
|
12878
|
+
reader.onload = function (ev) {
|
|
12879
|
+
var src = ev.target && ev.target.result;
|
|
12880
|
+
if (src) {
|
|
12881
|
+
editorEl.focus();
|
|
12882
|
+
document.execCommand("insertImage", false, src);
|
|
12883
|
+
notifyChange();
|
|
12884
|
+
}
|
|
12885
|
+
};
|
|
12886
|
+
reader.readAsDataURL(file);
|
|
12887
|
+
}
|
|
12888
|
+
};
|
|
12889
|
+
input.click();
|
|
12890
|
+
}
|
|
12891
|
+
|
|
12892
|
+
function undo() {
|
|
12893
|
+
editorEl.focus();
|
|
12894
|
+
document.execCommand("undo", false, null);
|
|
12895
|
+
refreshToolbar();
|
|
12896
|
+
notifyChange();
|
|
12897
|
+
}
|
|
12898
|
+
function redo() {
|
|
12899
|
+
editorEl.focus();
|
|
12900
|
+
document.execCommand("redo", false, null);
|
|
12901
|
+
refreshToolbar();
|
|
12902
|
+
notifyChange();
|
|
12903
|
+
}
|
|
12904
|
+
|
|
12905
|
+
function addBtn(iconStr, title, onClick, dataCommand, dataValue) {
|
|
12906
|
+
var btn = createToolbarButton({
|
|
12907
|
+
iconStr: iconStr,
|
|
12908
|
+
title: title,
|
|
12909
|
+
onClick: function () {
|
|
12910
|
+
if (disabled) return;
|
|
12911
|
+
onClick();
|
|
12912
|
+
}});
|
|
12913
|
+
if (dataCommand) btn.setAttribute("data-command", dataCommand);
|
|
12914
|
+
if (dataValue != null) btn.setAttribute("data-value", dataValue);
|
|
12915
|
+
toolbar.appendChild(btn);
|
|
12916
|
+
}
|
|
12917
|
+
|
|
12918
|
+
addBtn("IconBold", "Bold (Ctrl+B)", function () { exec("bold"); }, "bold");
|
|
12919
|
+
addBtn("IconItalic", "Italic (Ctrl+I)", function () { exec("italic"); }, "italic");
|
|
12920
|
+
addBtn("IconUnderline", "Underline (Ctrl+U)", function () { exec("underline"); }, "underline");
|
|
12921
|
+
toolbar.appendChild(createSeparator());
|
|
12922
|
+
addBtn("IconH1", "Heading 1", function () { exec("formatBlock", "h1"); }, "formatBlock", "h1");
|
|
12923
|
+
addBtn("IconH2", "Heading 2", function () { exec("formatBlock", "h2"); }, "formatBlock", "h2");
|
|
12924
|
+
addBtn("IconH3", "Heading 3", function () { exec("formatBlock", "h3"); }, "formatBlock", "h3");
|
|
12925
|
+
toolbar.appendChild(createSeparator());
|
|
12926
|
+
addBtn("IconList", "Bullet List", function () { exec("insertUnorderedList"); }, "insertUnorderedList");
|
|
12927
|
+
addBtn("IconListNumbers", "Ordered List", function () { exec("insertOrderedList"); }, "insertOrderedList");
|
|
12928
|
+
toolbar.appendChild(createSeparator());
|
|
12929
|
+
addBtn("IconAlignLeft", "Align Left", function () { exec("justifyLeft"); }, "justifyLeft", "left");
|
|
12930
|
+
addBtn("IconAlignCenter", "Align Center", function () { exec("justifyCenter"); }, "justifyCenter", "center");
|
|
12931
|
+
addBtn("IconAlignRight", "Align Right", function () { exec("justifyRight"); }, "justifyRight", "right");
|
|
12932
|
+
toolbar.appendChild(createSeparator());
|
|
12933
|
+
addBtn("IconCode", "Code Block", insertCodeBlock, "formatBlock", "pre");
|
|
12934
|
+
addBtn("IconLink", "Add Link", addLink, "link");
|
|
12935
|
+
addBtn("IconPhoto", "Insert Image", addImage);
|
|
12936
|
+
toolbar.appendChild(createSeparator());
|
|
12937
|
+
addBtn("IconArrowBackUp", "Undo", undo);
|
|
12938
|
+
addBtn("IconArrowForwardUp", "Redo", redo);
|
|
12939
|
+
|
|
12940
|
+
editorEl.addEventListener("input", function () {
|
|
12941
|
+
updatePlaceholder();
|
|
12942
|
+
refreshToolbar();
|
|
12943
|
+
notifyChange();
|
|
12944
|
+
});
|
|
12945
|
+
editorEl.addEventListener("keyup", refreshToolbar);
|
|
12946
|
+
editorEl.addEventListener("mouseup", refreshToolbar);
|
|
12947
|
+
editorEl.addEventListener("focus", refreshToolbar);
|
|
12948
|
+
|
|
12949
|
+
if (placeholder) {
|
|
12950
|
+
var placeholderStyles = document.createElement("style");
|
|
12951
|
+
placeholderStyles.textContent =
|
|
12952
|
+
".rich-text-editor-content.empty:before{content:attr(data-placeholder);color:var(--color-neutral-400);pointer-events:none}";
|
|
12953
|
+
wrapper.appendChild(placeholderStyles);
|
|
12954
|
+
}
|
|
12955
|
+
|
|
12956
|
+
wrapper.appendChild(toolbar);
|
|
12957
|
+
wrapper.appendChild(editorEl);
|
|
12958
|
+
|
|
12959
|
+
wrapper.getInput = function () {
|
|
12960
|
+
return editorEl;
|
|
12961
|
+
};
|
|
12962
|
+
wrapper.getValue = function () {
|
|
12963
|
+
return getHtml();
|
|
12964
|
+
};
|
|
12965
|
+
wrapper.setValue = function (v) {
|
|
12966
|
+
setHtml(v);
|
|
12967
|
+
};
|
|
12968
|
+
wrapper.setDisabled = function (d) {
|
|
12969
|
+
disabled = !!d;
|
|
12970
|
+
editorEl.contentEditable = !disabled;
|
|
12971
|
+
toolbar.querySelectorAll("button").forEach(function (b) {
|
|
12972
|
+
b.disabled = disabled;
|
|
12973
|
+
});
|
|
12974
|
+
};
|
|
12975
|
+
|
|
12976
|
+
return wrapper;
|
|
12977
|
+
}
|
|
12978
|
+
|
|
12979
|
+
global.RichTextEditorComponent = {
|
|
12980
|
+
create: create,
|
|
12981
|
+
};
|
|
12982
|
+
})(typeof window !== "undefined" ? window : undefined);
|
|
12983
|
+
|
|
12984
|
+
|
|
12985
|
+
|
|
12986
|
+
// ============================================
|
|
12987
|
+
// File 25/42: components/checkbox.js
|
|
12129
12988
|
// ============================================
|
|
12130
12989
|
|
|
12131
12990
|
/**
|
|
@@ -12164,10 +13023,18 @@
|
|
|
12164
13023
|
};
|
|
12165
13024
|
|
|
12166
13025
|
var CHECKBOX_BASE_CLASS =
|
|
12167
|
-
"flex items-center justify-center rounded-2 border-1/2 border-borderColor-border-primary bg-fill-quarternary-fill-white p-4 transition-all
|
|
13026
|
+
"flex items-center justify-center rounded-2 border-1/2 border-borderColor-border-primary bg-fill-quarternary-fill-white p-4 transition-all";
|
|
13027
|
+
|
|
13028
|
+
var CHECKBOX_ACTIVE_CLASS =
|
|
13029
|
+
"hover:border-primary-base hover:shadow-primary-focused cursor-pointer";
|
|
13030
|
+
|
|
13031
|
+
var CHECKBOX_DISABLED_CLASS =
|
|
13032
|
+
"cursor-not-allowed opacity-50";
|
|
12168
13033
|
|
|
12169
13034
|
var CHECKBOX_CHECKED_CLASS =
|
|
12170
|
-
"data-checked:border-transparent data-checked:bg-primary-base
|
|
13035
|
+
"data-checked:border-transparent data-checked:bg-primary-base";
|
|
13036
|
+
var CHECKBOX_CHECKED_ACTIVE_CLASS =
|
|
13037
|
+
"data-checked:hover:border-primary-base data-checked:hover:shadow-primary-focused";
|
|
12171
13038
|
|
|
12172
13039
|
var LABEL_BASE_CLASS =
|
|
12173
13040
|
"cursor-pointer pb-0 text-reg-12 leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70";
|
|
@@ -12231,12 +13098,16 @@
|
|
|
12231
13098
|
|
|
12232
13099
|
// Custom checkbox visual
|
|
12233
13100
|
var checkboxBox = document.createElement("div");
|
|
12234
|
-
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
13101
|
+
function applyCheckboxBoxClasses() {
|
|
13102
|
+
var sizeClass = CHECKBOX_SIZES[size] || CHECKBOX_SIZES.default;
|
|
13103
|
+
checkboxBox.className = join(
|
|
13104
|
+
CHECKBOX_BASE_CLASS,
|
|
13105
|
+
disabled ? CHECKBOX_DISABLED_CLASS : join(CHECKBOX_ACTIVE_CLASS, CHECKBOX_CHECKED_ACTIVE_CLASS),
|
|
13106
|
+
CHECKBOX_CHECKED_CLASS,
|
|
13107
|
+
sizeClass
|
|
13108
|
+
);
|
|
13109
|
+
}
|
|
13110
|
+
applyCheckboxBoxClasses();
|
|
12240
13111
|
checkboxBox.setAttribute("role", "checkbox");
|
|
12241
13112
|
checkboxBox.setAttribute("tabindex", disabled ? "-1" : "0");
|
|
12242
13113
|
checkboxBox.setAttribute("aria-checked", indeterminate ? "mixed" : checked ? "true" : "false");
|
|
@@ -12353,6 +13224,7 @@
|
|
|
12353
13224
|
} else {
|
|
12354
13225
|
checkboxBox.removeAttribute("aria-disabled");
|
|
12355
13226
|
}
|
|
13227
|
+
applyCheckboxBoxClasses();
|
|
12356
13228
|
updateCheckedState();
|
|
12357
13229
|
};
|
|
12358
13230
|
|
|
@@ -12385,7 +13257,210 @@
|
|
|
12385
13257
|
|
|
12386
13258
|
|
|
12387
13259
|
// ============================================
|
|
12388
|
-
// File
|
|
13260
|
+
// File 26/42: components/checkbox-group.js
|
|
13261
|
+
// ============================================
|
|
13262
|
+
|
|
13263
|
+
/**
|
|
13264
|
+
* CheckboxGroup Component (vanilla JS)
|
|
13265
|
+
* Multi-select via checkboxes; same API as MultiSelect (options, value array, onValuesChange).
|
|
13266
|
+
* Uses input.js-style variants and sizes for the group wrapper.
|
|
13267
|
+
*/
|
|
13268
|
+
|
|
13269
|
+
(function (global) {
|
|
13270
|
+
|
|
13271
|
+
// Wrapper classes aligned with input.js variants
|
|
13272
|
+
var WRAPPER_CLASS = {
|
|
13273
|
+
base:
|
|
13274
|
+
"group flex flex-col border-1/2 border-border-primary rounded-4 text-typography-primary-text w-full transition-all ease-in-out group-has-[:disabled]:cursor-not-allowed group-has-[:disabled]:border-border-primary group-has-[:disabled]:bg-fill-tertiary-fill-light-gray group-has-[:disabled]:text-typography-quaternary-text",
|
|
13275
|
+
default:
|
|
13276
|
+
"bg-fill-quarternary-fill-white hover:border-primary-base focus-within:border-primary-base",
|
|
13277
|
+
error:
|
|
13278
|
+
"border-error-base bg-fill-quarternary-fill-white hover:border-error-base focus-within:border-error-base",
|
|
13279
|
+
warning:
|
|
13280
|
+
"border-warning-base bg-fill-quarternary-fill-white hover:border-warning-base focus-within:border-warning-base",
|
|
13281
|
+
success:
|
|
13282
|
+
"border-success-base bg-fill-quarternary-fill-white hover:border-success-base focus-within:border-success-base",
|
|
13283
|
+
borderless:
|
|
13284
|
+
"border-none shadow-none rounded-0 bg-fill-quarternary-fill-white",
|
|
13285
|
+
inline:
|
|
13286
|
+
"border-transparent shadow-none rounded-0 bg-fill-quarternary-fill-white hover:bg-fill-tertiary-fill-light-gray focus-within:border-transparent focus:bg-fill-tertiary-fill-light-gray focus-within:bg-fill-tertiary-fill-light-gray",
|
|
13287
|
+
sizeDefault: "px-12 py-6 gap-6",
|
|
13288
|
+
sizeLarge: "px-12 py-8 gap-8",
|
|
13289
|
+
sizeSmall: "px-12 py-4 gap-4",
|
|
13290
|
+
disabled:
|
|
13291
|
+
"cursor-not-allowed border-border-primary bg-fill-tertiary-fill-light-gray text-typography-quaternary-text hover:border-border-primary",
|
|
13292
|
+
};
|
|
13293
|
+
|
|
13294
|
+
function join() {
|
|
13295
|
+
return Array.prototype.filter.call(arguments, Boolean).join(" ");
|
|
13296
|
+
}
|
|
13297
|
+
|
|
13298
|
+
function getOptionValue(opt) {
|
|
13299
|
+
return opt.value !== undefined && opt.value !== null
|
|
13300
|
+
? opt.value
|
|
13301
|
+
: opt.slug || opt.id;
|
|
13302
|
+
}
|
|
13303
|
+
|
|
13304
|
+
function getOptionLabel(opt) {
|
|
13305
|
+
return opt.label || opt.name || opt.display_name || opt.value;
|
|
13306
|
+
}
|
|
13307
|
+
|
|
13308
|
+
function getDep(name) {
|
|
13309
|
+
if (typeof global.FlowUI !== "undefined" && typeof global.FlowUI._getComponent === "function") {
|
|
13310
|
+
var c = global.FlowUI._getComponent(name);
|
|
13311
|
+
if (c) return c;
|
|
13312
|
+
}
|
|
13313
|
+
return global[name];
|
|
13314
|
+
}
|
|
13315
|
+
|
|
13316
|
+
/**
|
|
13317
|
+
* Create a checkbox group component (multiselect-like: multiple values, options array)
|
|
13318
|
+
* @param {Object} config
|
|
13319
|
+
* @param {string} [config.fieldId] - Field ID for state management
|
|
13320
|
+
* @param {Array} config.options - Array of { value, label } or { slug, display_name }
|
|
13321
|
+
* @param {Array} [config.value] - Current selected values (array)
|
|
13322
|
+
* @param {Function} config.onValuesChange - Change handler (values: string[])
|
|
13323
|
+
* @param {boolean} [config.disabled] - Whether all checkboxes are disabled
|
|
13324
|
+
* @param {string} [config.variant] - 'default' | 'error' | 'warning' | 'success' | 'borderless' | 'inline'
|
|
13325
|
+
* @param {string} [config.size] - 'default' | 'large' | 'small'
|
|
13326
|
+
* @param {string} [config.layout] - 'vertical' | 'horizontal'
|
|
13327
|
+
* @param {string} [config.className] - Extra class on wrapper
|
|
13328
|
+
* @returns {HTMLElement} CheckboxGroup container element
|
|
13329
|
+
*/
|
|
13330
|
+
function createCheckboxGroup(config) {
|
|
13331
|
+
var fieldId = config.fieldId;
|
|
13332
|
+
var options = config.options || [];
|
|
13333
|
+
var onValuesChange = config.onValuesChange;
|
|
13334
|
+
var variant = config.variant || "default";
|
|
13335
|
+
var size = config.size || "default";
|
|
13336
|
+
var disabled = config.disabled === true;
|
|
13337
|
+
var layout = config.layout || "vertical";
|
|
13338
|
+
var className = config.className || "";
|
|
13339
|
+
|
|
13340
|
+
var values = Array.isArray(config.value)
|
|
13341
|
+
? config.value.slice()
|
|
13342
|
+
: Array.isArray(config.values)
|
|
13343
|
+
? config.values.slice()
|
|
13344
|
+
: [];
|
|
13345
|
+
|
|
13346
|
+
var Checkbox = getDep("Checkbox");
|
|
13347
|
+
if (!Checkbox || typeof Checkbox.create !== "function") {
|
|
13348
|
+
throw new Error("CheckboxGroup requires the Checkbox component. Load checkbox.js before checkbox-group.js.");
|
|
13349
|
+
}
|
|
13350
|
+
|
|
13351
|
+
var container = document.createElement("div");
|
|
13352
|
+
container.setAttribute("role", "group");
|
|
13353
|
+
container.setAttribute("aria-label", config.ariaLabel || "Checkbox group");
|
|
13354
|
+
if (fieldId) container.setAttribute("data-field-id", fieldId);
|
|
13355
|
+
|
|
13356
|
+
var sizeClass = size === "large" ? WRAPPER_CLASS.sizeLarge : size === "small" ? WRAPPER_CLASS.sizeSmall : WRAPPER_CLASS.sizeDefault;
|
|
13357
|
+
function applyWrapperClasses() {
|
|
13358
|
+
container.className = join(
|
|
13359
|
+
WRAPPER_CLASS.base,
|
|
13360
|
+
disabled ? WRAPPER_CLASS.disabled : (WRAPPER_CLASS[variant] || WRAPPER_CLASS.default),
|
|
13361
|
+
sizeClass,
|
|
13362
|
+
layout === "horizontal" ? "flex-row flex-wrap" : "flex-col",
|
|
13363
|
+
"custom-checkbox-group",
|
|
13364
|
+
className
|
|
13365
|
+
);
|
|
13366
|
+
}
|
|
13367
|
+
applyWrapperClasses();
|
|
13368
|
+
container.setAttribute("data-checkbox-group-variant", variant);
|
|
13369
|
+
|
|
13370
|
+
function isSelected(optionValue) {
|
|
13371
|
+
return values.some(function (v) {
|
|
13372
|
+
return v === optionValue || String(v) === String(optionValue);
|
|
13373
|
+
});
|
|
13374
|
+
}
|
|
13375
|
+
|
|
13376
|
+
var optionsContainer = document.createElement("div");
|
|
13377
|
+
optionsContainer.className = join(
|
|
13378
|
+
"flex gap-8",
|
|
13379
|
+
layout === "horizontal" ? "flex-row flex-wrap" : "flex-col"
|
|
13380
|
+
);
|
|
13381
|
+
|
|
13382
|
+
function buildOptions() {
|
|
13383
|
+
optionsContainer.innerHTML = "";
|
|
13384
|
+
if (options.length === 0) {
|
|
13385
|
+
var empty = document.createElement("div");
|
|
13386
|
+
empty.className = "!text-reg-13 text-typography-quaternary-text py-4";
|
|
13387
|
+
empty.textContent = "No options available";
|
|
13388
|
+
optionsContainer.appendChild(empty);
|
|
13389
|
+
return;
|
|
13390
|
+
}
|
|
13391
|
+
|
|
13392
|
+
options.forEach(function (opt, index) {
|
|
13393
|
+
var optionValue = getOptionValue(opt);
|
|
13394
|
+
var optionLabel = getOptionLabel(opt);
|
|
13395
|
+
var optionDisabled = disabled || !!opt.disabled;
|
|
13396
|
+
var checked = isSelected(optionValue);
|
|
13397
|
+
|
|
13398
|
+
var cb = Checkbox.create({
|
|
13399
|
+
id: (fieldId || "cbg") + "-" + index,
|
|
13400
|
+
name: fieldId ? fieldId + "[]" : "checkbox-group-" + index,
|
|
13401
|
+
checked: checked,
|
|
13402
|
+
disabled: optionDisabled,
|
|
13403
|
+
label: optionLabel,
|
|
13404
|
+
align: "left",
|
|
13405
|
+
size: size === "large" ? "large" : size === "small" ? "small" : "default",
|
|
13406
|
+
onChange: function (isChecked) {
|
|
13407
|
+
if (optionDisabled) return;
|
|
13408
|
+
if (isChecked) {
|
|
13409
|
+
if (!values.some(function (v) { return v === optionValue || String(v) === String(optionValue); })) {
|
|
13410
|
+
values.push(optionValue);
|
|
13411
|
+
}
|
|
13412
|
+
} else {
|
|
13413
|
+
var idx = values.findIndex(function (v) {
|
|
13414
|
+
return v === optionValue || String(v) === String(optionValue);
|
|
13415
|
+
});
|
|
13416
|
+
if (idx >= 0) values.splice(idx, 1);
|
|
13417
|
+
}
|
|
13418
|
+
if (onValuesChange) onValuesChange(values.slice());
|
|
13419
|
+
},
|
|
13420
|
+
});
|
|
13421
|
+
optionsContainer.appendChild(cb);
|
|
13422
|
+
});
|
|
13423
|
+
}
|
|
13424
|
+
|
|
13425
|
+
buildOptions();
|
|
13426
|
+
container.appendChild(optionsContainer);
|
|
13427
|
+
|
|
13428
|
+
container.updateValues = function (newValues) {
|
|
13429
|
+
values = Array.isArray(newValues) ? newValues.slice() : [];
|
|
13430
|
+
buildOptions();
|
|
13431
|
+
};
|
|
13432
|
+
|
|
13433
|
+
container.setDisabled = function (isDisabled) {
|
|
13434
|
+
disabled = !!isDisabled;
|
|
13435
|
+
applyWrapperClasses();
|
|
13436
|
+
var wrappers = optionsContainer.querySelectorAll(":scope > div");
|
|
13437
|
+
for (var i = 0; i < wrappers.length; i++) {
|
|
13438
|
+
if (typeof wrappers[i].setDisabled === "function") wrappers[i].setDisabled(disabled);
|
|
13439
|
+
}
|
|
13440
|
+
};
|
|
13441
|
+
|
|
13442
|
+
container.setVariant = function (v) {
|
|
13443
|
+
variant = v;
|
|
13444
|
+
container.setAttribute("data-checkbox-group-variant", v);
|
|
13445
|
+
applyWrapperClasses();
|
|
13446
|
+
};
|
|
13447
|
+
|
|
13448
|
+
container.getValues = function () {
|
|
13449
|
+
return values.slice();
|
|
13450
|
+
};
|
|
13451
|
+
|
|
13452
|
+
return container;
|
|
13453
|
+
}
|
|
13454
|
+
|
|
13455
|
+
global.CheckboxGroup = {
|
|
13456
|
+
create: createCheckboxGroup,
|
|
13457
|
+
};
|
|
13458
|
+
})(typeof window !== "undefined" ? window : undefined);
|
|
13459
|
+
|
|
13460
|
+
|
|
13461
|
+
|
|
13462
|
+
// ============================================
|
|
13463
|
+
// File 27/42: components/radio-group.js
|
|
12389
13464
|
// ============================================
|
|
12390
13465
|
|
|
12391
13466
|
/**
|
|
@@ -12796,7 +13871,296 @@
|
|
|
12796
13871
|
|
|
12797
13872
|
|
|
12798
13873
|
// ============================================
|
|
12799
|
-
// File
|
|
13874
|
+
// File 28/42: components/card-select.js
|
|
13875
|
+
// ============================================
|
|
13876
|
+
|
|
13877
|
+
/**
|
|
13878
|
+
* CardSelect Component (vanilla JS)
|
|
13879
|
+
* Full-width clickable card selection with icon, title, description, and check indicator.
|
|
13880
|
+
* Drop-in replacement / upgrade to RadioGroup when visual card UI is preferred.
|
|
13881
|
+
*/
|
|
13882
|
+
|
|
13883
|
+
(function (global) {
|
|
13884
|
+
|
|
13885
|
+
var COLORS = {
|
|
13886
|
+
selectedBorder: "#175259",
|
|
13887
|
+
unselectedBorder: "#e5e7eb",
|
|
13888
|
+
selectedBg: "#f0f9f8",
|
|
13889
|
+
unselectedBg: "#ffffff",
|
|
13890
|
+
selectedShadow: "0px 0px 0px 2px #e9f7f5",
|
|
13891
|
+
unselectedShadow: "0px 1.5px 4px -1px rgba(10,9,11,0.07)",
|
|
13892
|
+
hoverBorder: "#9ca3af",
|
|
13893
|
+
hoverShadow: "0px 5px 13px -5px rgba(10,9,11,0.05), 0px 2px 4px -1px rgba(10,9,11,0.02)",
|
|
13894
|
+
iconSelectedBg: "#d0ede9",
|
|
13895
|
+
iconUnselectedBg: "#f3f4f6",
|
|
13896
|
+
iconSelectedColor: "#175259",
|
|
13897
|
+
iconUnselectedColor: "#6b7280",
|
|
13898
|
+
titleSelected: "#175259",
|
|
13899
|
+
titleUnselected: "#111827",
|
|
13900
|
+
descSelected: "#35b18b",
|
|
13901
|
+
descUnselected: "#6b7280",
|
|
13902
|
+
checkBorderSelected: "#175259",
|
|
13903
|
+
checkBorderUnselected: "#d1d5db",
|
|
13904
|
+
checkBgSelected: "#175259",
|
|
13905
|
+
checkBgUnselected: "transparent",
|
|
13906
|
+
};
|
|
13907
|
+
|
|
13908
|
+
var CHECK_ICON =
|
|
13909
|
+
'<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 5l2.5 2.5L8 3" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
|
13910
|
+
|
|
13911
|
+
function join() {
|
|
13912
|
+
return Array.prototype.filter.call(arguments, Boolean).join(" ");
|
|
13913
|
+
}
|
|
13914
|
+
|
|
13915
|
+
function applyCardStyles(card, isSelected) {
|
|
13916
|
+
card.style.borderColor = isSelected ? COLORS.selectedBorder : COLORS.unselectedBorder;
|
|
13917
|
+
card.style.background = isSelected ? COLORS.selectedBg : COLORS.unselectedBg;
|
|
13918
|
+
card.style.boxShadow = isSelected ? COLORS.selectedShadow : COLORS.unselectedShadow;
|
|
13919
|
+
}
|
|
13920
|
+
|
|
13921
|
+
function applyIconStyles(iconWrapper, isSelected) {
|
|
13922
|
+
iconWrapper.style.background = isSelected ? COLORS.iconSelectedBg : COLORS.iconUnselectedBg;
|
|
13923
|
+
iconWrapper.style.color = isSelected ? COLORS.iconSelectedColor : COLORS.iconUnselectedColor;
|
|
13924
|
+
}
|
|
13925
|
+
|
|
13926
|
+
function applyTitleStyles(titleEl, isSelected) {
|
|
13927
|
+
titleEl.style.color = isSelected ? COLORS.titleSelected : COLORS.titleUnselected;
|
|
13928
|
+
}
|
|
13929
|
+
|
|
13930
|
+
function applyDescStyles(descEl, isSelected) {
|
|
13931
|
+
descEl.style.color = isSelected ? COLORS.descSelected : COLORS.descUnselected;
|
|
13932
|
+
}
|
|
13933
|
+
|
|
13934
|
+
function applyCheckStyles(checkEl, isSelected) {
|
|
13935
|
+
checkEl.style.borderColor = isSelected ? COLORS.checkBorderSelected : COLORS.checkBorderUnselected;
|
|
13936
|
+
checkEl.style.background = isSelected ? COLORS.checkBgSelected : COLORS.checkBgUnselected;
|
|
13937
|
+
checkEl.innerHTML = isSelected ? CHECK_ICON : "";
|
|
13938
|
+
}
|
|
13939
|
+
|
|
13940
|
+
/**
|
|
13941
|
+
* Create a card select component
|
|
13942
|
+
* @param {Object} config
|
|
13943
|
+
* @param {string} [config.name] - name attribute for the group (used for id generation)
|
|
13944
|
+
* @param {Array} config.options - array of { value, label, description?, icon?, disabled? }
|
|
13945
|
+
* @param {string} [config.defaultValue] - initial selected value
|
|
13946
|
+
* @param {string} [config.value] - controlled value (takes priority over defaultValue)
|
|
13947
|
+
* @param {boolean} [config.disabled] - disable all cards
|
|
13948
|
+
* @param {string} [config.className] - extra class on wrapper
|
|
13949
|
+
* @param {Function} [config.onChange] - change handler (receives selected value)
|
|
13950
|
+
* @returns {HTMLElement} wrapper element with getValue/setValue/setDisabled API
|
|
13951
|
+
*/
|
|
13952
|
+
function create(config) {
|
|
13953
|
+
var opts = config || {};
|
|
13954
|
+
var name = opts.name || "card-select-" + Math.random().toString(36).substr(2, 9);
|
|
13955
|
+
var options = opts.options || [];
|
|
13956
|
+
var defaultValue = opts.defaultValue;
|
|
13957
|
+
var selectedValue = opts.value !== undefined ? opts.value : defaultValue;
|
|
13958
|
+
var disabled = !!opts.disabled;
|
|
13959
|
+
var className = opts.className || "";
|
|
13960
|
+
var onChange = opts.onChange;
|
|
13961
|
+
|
|
13962
|
+
// Wrapper container
|
|
13963
|
+
var wrapper = document.createElement("div");
|
|
13964
|
+
wrapper.setAttribute("role", "radiogroup");
|
|
13965
|
+
wrapper.setAttribute("dir", "ltr");
|
|
13966
|
+
wrapper.className = join("flex flex-col gap-3 w-full", className);
|
|
13967
|
+
|
|
13968
|
+
function updateAllCards(newValue) {
|
|
13969
|
+
var cards = wrapper.querySelectorAll("[data-card-value]");
|
|
13970
|
+
cards.forEach(function (card) {
|
|
13971
|
+
var cv = card.dataset.cardValue;
|
|
13972
|
+
var active = cv === newValue;
|
|
13973
|
+
applyCardStyles(card, active);
|
|
13974
|
+
card.setAttribute("aria-checked", active ? "true" : "false");
|
|
13975
|
+
var iw = card.querySelector("[data-icon]");
|
|
13976
|
+
var titleEl = card.querySelector("[data-title]");
|
|
13977
|
+
var descEl = card.querySelector("[data-desc]");
|
|
13978
|
+
var checkEl = card.querySelector("[data-check]");
|
|
13979
|
+
if (iw) applyIconStyles(iw, active);
|
|
13980
|
+
if (titleEl) applyTitleStyles(titleEl, active);
|
|
13981
|
+
if (descEl) applyDescStyles(descEl, active);
|
|
13982
|
+
if (checkEl) applyCheckStyles(checkEl, active);
|
|
13983
|
+
});
|
|
13984
|
+
}
|
|
13985
|
+
|
|
13986
|
+
options.forEach(function (option, index) {
|
|
13987
|
+
var optionValue = option.value;
|
|
13988
|
+
var optionLabel = option.label || option.value;
|
|
13989
|
+
var optionDesc = option.description || "";
|
|
13990
|
+
var optionIcon = option.icon || "";
|
|
13991
|
+
var optionDisabled = disabled || !!option.disabled;
|
|
13992
|
+
var isSelected = optionValue === selectedValue;
|
|
13993
|
+
|
|
13994
|
+
// Card element
|
|
13995
|
+
var card = document.createElement("div");
|
|
13996
|
+
card.dataset.cardValue = optionValue;
|
|
13997
|
+
card.id = name + "-card-" + index;
|
|
13998
|
+
card.setAttribute("role", "radio");
|
|
13999
|
+
card.setAttribute("aria-checked", isSelected ? "true" : "false");
|
|
14000
|
+
card.setAttribute("tabindex", optionDisabled ? "-1" : "0");
|
|
14001
|
+
|
|
14002
|
+
card.style.cssText = [
|
|
14003
|
+
"display: flex",
|
|
14004
|
+
"align-items: flex-start",
|
|
14005
|
+
"gap: 16px",
|
|
14006
|
+
"padding: 18px 20px",
|
|
14007
|
+
"border-radius: 10px",
|
|
14008
|
+
"border: 1.5px solid " + (isSelected ? COLORS.selectedBorder : COLORS.unselectedBorder),
|
|
14009
|
+
"background: " + (isSelected ? COLORS.selectedBg : COLORS.unselectedBg),
|
|
14010
|
+
"cursor: " + (optionDisabled ? "not-allowed" : "pointer"),
|
|
14011
|
+
"transition: border-color 0.15s, background 0.15s, box-shadow 0.15s",
|
|
14012
|
+
"box-shadow: " + (isSelected ? COLORS.selectedShadow : COLORS.unselectedShadow),
|
|
14013
|
+
"user-select: none",
|
|
14014
|
+
optionDisabled ? "opacity: 0.5" : "",
|
|
14015
|
+
].filter(Boolean).join("; ");
|
|
14016
|
+
|
|
14017
|
+
// Icon wrapper (only rendered when icon is provided)
|
|
14018
|
+
if (optionIcon) {
|
|
14019
|
+
var iconWrapper = document.createElement("div");
|
|
14020
|
+
iconWrapper.dataset.icon = "";
|
|
14021
|
+
iconWrapper.style.cssText = [
|
|
14022
|
+
"flex-shrink: 0",
|
|
14023
|
+
"width: 44px",
|
|
14024
|
+
"height: 44px",
|
|
14025
|
+
"border-radius: 8px",
|
|
14026
|
+
"background: " + (isSelected ? COLORS.iconSelectedBg : COLORS.iconUnselectedBg),
|
|
14027
|
+
"display: flex",
|
|
14028
|
+
"align-items: center",
|
|
14029
|
+
"justify-content: center",
|
|
14030
|
+
"color: " + (isSelected ? COLORS.iconSelectedColor : COLORS.iconUnselectedColor),
|
|
14031
|
+
"transition: background 0.15s, color 0.15s",
|
|
14032
|
+
].join("; ");
|
|
14033
|
+
iconWrapper.innerHTML = optionIcon;
|
|
14034
|
+
card.appendChild(iconWrapper);
|
|
14035
|
+
}
|
|
14036
|
+
|
|
14037
|
+
// Text wrapper
|
|
14038
|
+
var textWrapper = document.createElement("div");
|
|
14039
|
+
textWrapper.style.cssText = "display: flex; flex-direction: column; gap: 4px; flex: 1;";
|
|
14040
|
+
|
|
14041
|
+
var titleEl = document.createElement("span");
|
|
14042
|
+
titleEl.dataset.title = "";
|
|
14043
|
+
titleEl.textContent = optionLabel;
|
|
14044
|
+
titleEl.style.cssText = [
|
|
14045
|
+
"font-size: 14px",
|
|
14046
|
+
"font-weight: 600",
|
|
14047
|
+
"color: " + (isSelected ? COLORS.titleSelected : COLORS.titleUnselected),
|
|
14048
|
+
"line-height: 1.4",
|
|
14049
|
+
"transition: color 0.15s",
|
|
14050
|
+
].join("; ");
|
|
14051
|
+
textWrapper.appendChild(titleEl);
|
|
14052
|
+
|
|
14053
|
+
if (optionDesc) {
|
|
14054
|
+
var descEl = document.createElement("span");
|
|
14055
|
+
descEl.dataset.desc = "";
|
|
14056
|
+
descEl.textContent = optionDesc;
|
|
14057
|
+
descEl.style.cssText = [
|
|
14058
|
+
"font-size: 12px",
|
|
14059
|
+
"color: " + (isSelected ? COLORS.descSelected : COLORS.descUnselected),
|
|
14060
|
+
"line-height: 1.5",
|
|
14061
|
+
"transition: color 0.15s",
|
|
14062
|
+
].join("; ");
|
|
14063
|
+
textWrapper.appendChild(descEl);
|
|
14064
|
+
}
|
|
14065
|
+
|
|
14066
|
+
card.appendChild(textWrapper);
|
|
14067
|
+
|
|
14068
|
+
// Check indicator (radio circle in top-right)
|
|
14069
|
+
var checkEl = document.createElement("div");
|
|
14070
|
+
checkEl.dataset.check = "";
|
|
14071
|
+
checkEl.style.cssText = [
|
|
14072
|
+
"flex-shrink: 0",
|
|
14073
|
+
"width: 18px",
|
|
14074
|
+
"height: 18px",
|
|
14075
|
+
"border-radius: 50%",
|
|
14076
|
+
"border: 2px solid " + (isSelected ? COLORS.checkBorderSelected : COLORS.checkBorderUnselected),
|
|
14077
|
+
"background: " + (isSelected ? COLORS.checkBgSelected : COLORS.checkBgUnselected),
|
|
14078
|
+
"display: flex",
|
|
14079
|
+
"align-items: center",
|
|
14080
|
+
"justify-content: center",
|
|
14081
|
+
"margin-top: 2px",
|
|
14082
|
+
"transition: all 0.15s",
|
|
14083
|
+
].join("; ");
|
|
14084
|
+
if (isSelected) {
|
|
14085
|
+
checkEl.innerHTML = CHECK_ICON;
|
|
14086
|
+
}
|
|
14087
|
+
card.appendChild(checkEl);
|
|
14088
|
+
|
|
14089
|
+
// Hover and focus styles
|
|
14090
|
+
if (!optionDisabled) {
|
|
14091
|
+
card.addEventListener("mouseenter", function () {
|
|
14092
|
+
if (card.getAttribute("aria-checked") !== "true") {
|
|
14093
|
+
card.style.borderColor = COLORS.hoverBorder;
|
|
14094
|
+
card.style.boxShadow = COLORS.hoverShadow;
|
|
14095
|
+
}
|
|
14096
|
+
});
|
|
14097
|
+
card.addEventListener("mouseleave", function () {
|
|
14098
|
+
if (card.getAttribute("aria-checked") !== "true") {
|
|
14099
|
+
card.style.borderColor = COLORS.unselectedBorder;
|
|
14100
|
+
card.style.boxShadow = COLORS.unselectedShadow;
|
|
14101
|
+
}
|
|
14102
|
+
});
|
|
14103
|
+
|
|
14104
|
+
// Click handler
|
|
14105
|
+
card.addEventListener("click", function () {
|
|
14106
|
+
if (optionDisabled || disabled) return;
|
|
14107
|
+
selectedValue = optionValue;
|
|
14108
|
+
updateAllCards(selectedValue);
|
|
14109
|
+
if (typeof onChange === "function") {
|
|
14110
|
+
onChange(selectedValue);
|
|
14111
|
+
}
|
|
14112
|
+
});
|
|
14113
|
+
|
|
14114
|
+
// Keyboard support
|
|
14115
|
+
card.addEventListener("keydown", function (e) {
|
|
14116
|
+
if (optionDisabled || disabled) return;
|
|
14117
|
+
if (e.key === " " || e.key === "Enter") {
|
|
14118
|
+
e.preventDefault();
|
|
14119
|
+
card.click();
|
|
14120
|
+
}
|
|
14121
|
+
});
|
|
14122
|
+
}
|
|
14123
|
+
|
|
14124
|
+
wrapper.appendChild(card);
|
|
14125
|
+
});
|
|
14126
|
+
|
|
14127
|
+
// Public API
|
|
14128
|
+
wrapper.getValue = function () {
|
|
14129
|
+
return selectedValue !== undefined ? selectedValue : null;
|
|
14130
|
+
};
|
|
14131
|
+
|
|
14132
|
+
wrapper.setValue = function (newValue) {
|
|
14133
|
+
selectedValue = newValue;
|
|
14134
|
+
updateAllCards(newValue);
|
|
14135
|
+
};
|
|
14136
|
+
|
|
14137
|
+
wrapper.setDisabled = function (isDisabled) {
|
|
14138
|
+
disabled = !!isDisabled;
|
|
14139
|
+
wrapper.querySelectorAll("[data-card-value]").forEach(function (card) {
|
|
14140
|
+
card.style.cursor = disabled ? "not-allowed" : "pointer";
|
|
14141
|
+
card.style.opacity = disabled ? "0.5" : "1";
|
|
14142
|
+
card.setAttribute("tabindex", disabled ? "-1" : "0");
|
|
14143
|
+
});
|
|
14144
|
+
};
|
|
14145
|
+
|
|
14146
|
+
return wrapper;
|
|
14147
|
+
}
|
|
14148
|
+
|
|
14149
|
+
var CardSelect = {
|
|
14150
|
+
create: create,
|
|
14151
|
+
};
|
|
14152
|
+
|
|
14153
|
+
if (typeof module !== "undefined" && module.exports) {
|
|
14154
|
+
module.exports = CardSelect;
|
|
14155
|
+
} else {
|
|
14156
|
+
global.CardSelect = CardSelect;
|
|
14157
|
+
}
|
|
14158
|
+
})(typeof window !== "undefined" ? window : undefined);
|
|
14159
|
+
|
|
14160
|
+
|
|
14161
|
+
|
|
14162
|
+
// ============================================
|
|
14163
|
+
// File 29/42: components/enumeration.js
|
|
12800
14164
|
// ============================================
|
|
12801
14165
|
|
|
12802
14166
|
/**
|
|
@@ -12808,7 +14172,7 @@
|
|
|
12808
14172
|
(function (global) {
|
|
12809
14173
|
|
|
12810
14174
|
var BASE_CLASS =
|
|
12811
|
-
"flex items-center border rounded-4 text-typography-primary-text gap-4 !text-reg-13";
|
|
14175
|
+
"flex items-center border-1/2 rounded-4 text-typography-primary-text gap-4 !text-reg-13";
|
|
12812
14176
|
|
|
12813
14177
|
var VARIANTS = {
|
|
12814
14178
|
default:
|
|
@@ -12832,7 +14196,7 @@
|
|
|
12832
14196
|
};
|
|
12833
14197
|
|
|
12834
14198
|
var DISABLED_CLASS =
|
|
12835
|
-
"pointer-events-none !cursor-not-allowed opacity-50";
|
|
14199
|
+
"pointer-events-none !cursor-not-allowed opacity-50 bg-fill-tertiary-fill-light-gray";
|
|
12836
14200
|
var READONLY_CLASS = "pointer-events-none";
|
|
12837
14201
|
|
|
12838
14202
|
var ITEM_BASE_CLASS =
|
|
@@ -12891,20 +14255,23 @@
|
|
|
12891
14255
|
var iconSize = opts.iconSize || "default";
|
|
12892
14256
|
var defaultValue = opts.defaultValue;
|
|
12893
14257
|
var disabled = opts.disabled === true;
|
|
12894
|
-
var readOnly = opts.readOnly === true;
|
|
12895
|
-
var className = opts.className || "";
|
|
12896
|
-
var onValueChange = opts.onValueChange;
|
|
12897
|
-
var children = opts.children;
|
|
12898
|
-
|
|
12899
|
-
var wrapper = document.createElement("div");
|
|
12900
|
-
|
|
12901
|
-
|
|
12902
|
-
|
|
12903
|
-
|
|
12904
|
-
|
|
12905
|
-
|
|
12906
|
-
|
|
12907
|
-
|
|
14258
|
+
var readOnly = opts.readOnly === true;
|
|
14259
|
+
var className = opts.className || "";
|
|
14260
|
+
var onValueChange = opts.onValueChange;
|
|
14261
|
+
var children = opts.children;
|
|
14262
|
+
|
|
14263
|
+
var wrapper = document.createElement("div");
|
|
14264
|
+
function applyWrapperClasses() {
|
|
14265
|
+
wrapper.className = join(
|
|
14266
|
+
BASE_CLASS,
|
|
14267
|
+
VARIANTS[variant] != null ? VARIANTS[variant] : VARIANTS.default,
|
|
14268
|
+
SIZES[size] != null ? SIZES[size] : SIZES.default,
|
|
14269
|
+
disabled ? DISABLED_CLASS : "",
|
|
14270
|
+
readOnly ? READONLY_CLASS : "",
|
|
14271
|
+
className
|
|
14272
|
+
);
|
|
14273
|
+
}
|
|
14274
|
+
applyWrapperClasses();
|
|
12908
14275
|
wrapper.setAttribute("data-enumeration-variant", variant);
|
|
12909
14276
|
|
|
12910
14277
|
var count =
|
|
@@ -12974,6 +14341,22 @@
|
|
|
12974
14341
|
}
|
|
12975
14342
|
}
|
|
12976
14343
|
|
|
14344
|
+
wrapper.setDisabled = function (d) {
|
|
14345
|
+
disabled = d === true;
|
|
14346
|
+
for (var j = 0; j < itemElements.length; j++) {
|
|
14347
|
+
itemElements[j].setAttribute("tabindex", disabled || readOnly ? "-1" : "0");
|
|
14348
|
+
}
|
|
14349
|
+
applyWrapperClasses();
|
|
14350
|
+
};
|
|
14351
|
+
|
|
14352
|
+
wrapper.setReadOnly = function (r) {
|
|
14353
|
+
readOnly = r === true;
|
|
14354
|
+
for (var j = 0; j < itemElements.length; j++) {
|
|
14355
|
+
itemElements[j].setAttribute("tabindex", disabled || readOnly ? "-1" : "0");
|
|
14356
|
+
}
|
|
14357
|
+
applyWrapperClasses();
|
|
14358
|
+
};
|
|
14359
|
+
|
|
12977
14360
|
return wrapper;
|
|
12978
14361
|
}
|
|
12979
14362
|
|
|
@@ -13015,7 +14398,7 @@
|
|
|
13015
14398
|
|
|
13016
14399
|
|
|
13017
14400
|
// ============================================
|
|
13018
|
-
// File
|
|
14401
|
+
// File 30/42: components/time-picker.js
|
|
13019
14402
|
// ============================================
|
|
13020
14403
|
|
|
13021
14404
|
/**
|
|
@@ -13376,7 +14759,7 @@
|
|
|
13376
14759
|
|
|
13377
14760
|
|
|
13378
14761
|
// ============================================
|
|
13379
|
-
// File
|
|
14762
|
+
// File 31/42: components/duration/duration-utils.js
|
|
13380
14763
|
// ============================================
|
|
13381
14764
|
|
|
13382
14765
|
/**
|
|
@@ -13546,7 +14929,7 @@
|
|
|
13546
14929
|
|
|
13547
14930
|
|
|
13548
14931
|
// ============================================
|
|
13549
|
-
// File
|
|
14932
|
+
// File 32/42: components/duration/duration-constants.js
|
|
13550
14933
|
// ============================================
|
|
13551
14934
|
|
|
13552
14935
|
/**
|
|
@@ -13598,7 +14981,7 @@
|
|
|
13598
14981
|
|
|
13599
14982
|
|
|
13600
14983
|
// ============================================
|
|
13601
|
-
// File
|
|
14984
|
+
// File 33/42: components/duration/duration.js
|
|
13602
14985
|
// ============================================
|
|
13603
14986
|
|
|
13604
14987
|
/**
|
|
@@ -13642,7 +15025,7 @@
|
|
|
13642
15025
|
sizeLarge: "px-12 py-8",
|
|
13643
15026
|
sizeSmall: "px-12 py-4",
|
|
13644
15027
|
disabled:
|
|
13645
|
-
"cursor-not-allowed border-border-primary bg-fill-tertiary-fill-light-gray text-typography-quaternary-text hover:border-border-primary
|
|
15028
|
+
"pointer-events-none cursor-not-allowed border-border-primary bg-fill-tertiary-fill-light-gray text-typography-quaternary-text hover:border-border-primary",
|
|
13646
15029
|
};
|
|
13647
15030
|
|
|
13648
15031
|
function join() {
|
|
@@ -14035,8 +15418,13 @@
|
|
|
14035
15418
|
};
|
|
14036
15419
|
container.setDisabled = function (d) {
|
|
14037
15420
|
disabled = !!d;
|
|
14038
|
-
triggerWrapper.
|
|
14039
|
-
|
|
15421
|
+
triggerWrapper.className = join(
|
|
15422
|
+
TRIGGER_CLASS.base,
|
|
15423
|
+
TRIGGER_CLASS[variant] != null ? TRIGGER_CLASS[variant] : TRIGGER_CLASS.default,
|
|
15424
|
+
size === "large" ? TRIGGER_CLASS.sizeLarge : size === "small" ? TRIGGER_CLASS.sizeSmall : TRIGGER_CLASS.sizeDefault,
|
|
15425
|
+
disabled ? TRIGGER_CLASS.disabled : "",
|
|
15426
|
+
className
|
|
15427
|
+
);
|
|
14040
15428
|
triggerWrapper.setAttribute("tabindex", disabled ? "-1" : "0");
|
|
14041
15429
|
if (disabled) popoverApi.hide();
|
|
14042
15430
|
};
|
|
@@ -14052,7 +15440,7 @@
|
|
|
14052
15440
|
|
|
14053
15441
|
|
|
14054
15442
|
// ============================================
|
|
14055
|
-
// File
|
|
15443
|
+
// File 34/42: components/date-time-picker/date-time-picker-utils.js
|
|
14056
15444
|
// ============================================
|
|
14057
15445
|
|
|
14058
15446
|
/**
|
|
@@ -14311,7 +15699,7 @@
|
|
|
14311
15699
|
|
|
14312
15700
|
|
|
14313
15701
|
// ============================================
|
|
14314
|
-
// File
|
|
15702
|
+
// File 35/42: components/date-time-picker/date-time-picker.js
|
|
14315
15703
|
// ============================================
|
|
14316
15704
|
|
|
14317
15705
|
/**
|
|
@@ -14556,13 +15944,15 @@
|
|
|
14556
15944
|
var displayMonth = validDate ? new Date(validDate.getTime()) : new Date();
|
|
14557
15945
|
|
|
14558
15946
|
var triggerWrapper = document.createElement("div");
|
|
14559
|
-
|
|
14560
|
-
|
|
14561
|
-
|
|
14562
|
-
|
|
14563
|
-
|
|
14564
|
-
|
|
14565
|
-
|
|
15947
|
+
function getTriggerClassName(disabledState) {
|
|
15948
|
+
return join(
|
|
15949
|
+
"group flex items-center border-1/2 border-border-primary rounded-4 text-typography-primary-text gap-x-8 w-full transition-all ease-in-out",
|
|
15950
|
+
"bg-fill-quarternary-fill-white hover:border-primary-base focus-within:border-primary-base",
|
|
15951
|
+
size === "large" ? "px-12 py-8" : size === "small" ? "px-12 py-4" : "px-12 py-6",
|
|
15952
|
+
disabledState ? "pointer-events-none cursor-not-allowed border-border-primary bg-fill-tertiary-fill-light-gray text-typography-quaternary-text hover:border-border-primary" : "cursor-pointer"
|
|
15953
|
+
);
|
|
15954
|
+
}
|
|
15955
|
+
triggerWrapper.className = getTriggerClassName(disabled);
|
|
14566
15956
|
triggerWrapper.setAttribute("role", "button");
|
|
14567
15957
|
triggerWrapper.setAttribute("tabindex", disabled ? "-1" : "0");
|
|
14568
15958
|
triggerWrapper.setAttribute("aria-haspopup", "dialog");
|
|
@@ -14830,8 +16220,7 @@
|
|
|
14830
16220
|
};
|
|
14831
16221
|
container.setDisabled = function (d) {
|
|
14832
16222
|
disabled = !!d;
|
|
14833
|
-
triggerWrapper.
|
|
14834
|
-
triggerWrapper.classList.toggle("opacity-60", disabled);
|
|
16223
|
+
triggerWrapper.className = getTriggerClassName(disabled);
|
|
14835
16224
|
triggerWrapper.setAttribute("tabindex", disabled ? "-1" : "0");
|
|
14836
16225
|
if (disabled) popoverApi.hide();
|
|
14837
16226
|
};
|
|
@@ -14847,7 +16236,7 @@
|
|
|
14847
16236
|
|
|
14848
16237
|
|
|
14849
16238
|
// ============================================
|
|
14850
|
-
// File
|
|
16239
|
+
// File 36/42: components/phone-input/phone-utils.js
|
|
14851
16240
|
// ============================================
|
|
14852
16241
|
|
|
14853
16242
|
/**
|
|
@@ -15010,7 +16399,7 @@
|
|
|
15010
16399
|
|
|
15011
16400
|
|
|
15012
16401
|
// ============================================
|
|
15013
|
-
// File
|
|
16402
|
+
// File 37/42: components/phone-input/phone-input.js
|
|
15014
16403
|
// ============================================
|
|
15015
16404
|
|
|
15016
16405
|
/**
|
|
@@ -15408,7 +16797,7 @@
|
|
|
15408
16797
|
|
|
15409
16798
|
|
|
15410
16799
|
// ============================================
|
|
15411
|
-
// File
|
|
16800
|
+
// File 38/42: components/file-input.js
|
|
15412
16801
|
// ============================================
|
|
15413
16802
|
|
|
15414
16803
|
/**
|
|
@@ -15452,6 +16841,15 @@
|
|
|
15452
16841
|
return ICONS.file;
|
|
15453
16842
|
}
|
|
15454
16843
|
|
|
16844
|
+
/** Resolve client: use FlowUI._getComponent when bundle has captured globals, else global.superleapClient (same as enum-select) */
|
|
16845
|
+
function getClient() {
|
|
16846
|
+
if (global.FlowUI && typeof global.FlowUI._getComponent === "function") {
|
|
16847
|
+
var c = global.FlowUI._getComponent("superleapClient");
|
|
16848
|
+
if (c) return c;
|
|
16849
|
+
}
|
|
16850
|
+
return global.superleapClient;
|
|
16851
|
+
}
|
|
16852
|
+
|
|
15455
16853
|
/**
|
|
15456
16854
|
* Upload file to S3
|
|
15457
16855
|
* @param {File} file - File to upload
|
|
@@ -15463,26 +16861,31 @@
|
|
|
15463
16861
|
formData.append("file", file, file.name);
|
|
15464
16862
|
formData.append("is_private", String(!!isPrivate));
|
|
15465
16863
|
|
|
15466
|
-
// Get upload
|
|
16864
|
+
// Get upload path - can be configured via global.S3_UPLOAD_URL
|
|
15467
16865
|
const uploadUrl = global.S3_UPLOAD_URL || "/org/file/upload";
|
|
15468
|
-
const baseUrl = global.SUPERLEAP_BASE_URL || "https://app.superleap.com/api/v1";
|
|
15469
|
-
const fullUrl = uploadUrl.startsWith("http") ? uploadUrl : `${baseUrl}${uploadUrl}`;
|
|
15470
16866
|
|
|
15471
|
-
//
|
|
15472
|
-
|
|
16867
|
+
// Base URL and API key from superleapClient only (same pattern as enum-select)
|
|
16868
|
+
var client = getClient();
|
|
16869
|
+
var baseUrl = null;
|
|
16870
|
+
var apiKey = null;
|
|
15473
16871
|
try {
|
|
15474
|
-
|
|
15475
|
-
|
|
15476
|
-
|
|
15477
|
-
: global.superleapClient;
|
|
16872
|
+
if (client && typeof client.getBaseUrl === "function") {
|
|
16873
|
+
baseUrl = client.getBaseUrl();
|
|
16874
|
+
}
|
|
15478
16875
|
if (client && typeof client.getSdk === "function") {
|
|
15479
|
-
|
|
15480
|
-
apiKey = sdk
|
|
16876
|
+
var sdk = client.getSdk();
|
|
16877
|
+
apiKey = sdk ? sdk.apiKey : null;
|
|
15481
16878
|
}
|
|
15482
16879
|
} catch (e) {
|
|
15483
|
-
console.warn("[S3FileUpload] Could not get
|
|
16880
|
+
console.warn("[S3FileUpload] Could not get client:", e);
|
|
16881
|
+
}
|
|
16882
|
+
|
|
16883
|
+
if (!baseUrl) {
|
|
16884
|
+
throw new Error("SuperLeap client not initialized. Call superleapClient.init({ baseUrl, apiKey }) first.");
|
|
15484
16885
|
}
|
|
15485
16886
|
|
|
16887
|
+
const fullUrl = uploadUrl.startsWith("http") ? uploadUrl : baseUrl.replace(/\/$/, "") + (uploadUrl.startsWith("/") ? uploadUrl : "/" + uploadUrl);
|
|
16888
|
+
|
|
15486
16889
|
const headers = {};
|
|
15487
16890
|
if (apiKey) {
|
|
15488
16891
|
headers.Authorization = `Bearer ${apiKey}`;
|
|
@@ -15526,8 +16929,36 @@
|
|
|
15526
16929
|
* @param {boolean} config.isPrivate - Whether files should be private
|
|
15527
16930
|
* @param {number} config.maxFiles - Maximum number of files (for multiple mode)
|
|
15528
16931
|
* @param {number} config.maxFileSize - Maximum file size in bytes
|
|
16932
|
+
* @param {boolean} [config.disabled] - Whether the file upload is disabled
|
|
16933
|
+
* @param {string} [config.variant] - 'default' | 'error' | 'warning' | 'success' | 'borderless' | 'inline'
|
|
16934
|
+
* @param {string} [config.inputSize] - 'default' | 'large' | 'small'
|
|
16935
|
+
* @param {string} [config.className] - Extra class on upload wrapper
|
|
15529
16936
|
* @returns {HTMLElement} Field element
|
|
15530
16937
|
*/
|
|
16938
|
+
var UPLOAD_WRAPPER_CLASS = {
|
|
16939
|
+
base:
|
|
16940
|
+
"group relative flex w-full items-center justify-between border-1/2 rounded-4 text-typography-primary-text w-full transition-all ease-in-out focus-within:outline-none group-has-[:disabled]:cursor-not-allowed group-has-[:disabled]:border-border-primary group-has-[:disabled]:bg-fill-tertiary-fill-light-gray group-has-[:disabled]:text-typography-quaternary-text group-has-[:disabled]:hover:border-border-primary",
|
|
16941
|
+
default:
|
|
16942
|
+
"border-border-primary bg-fill-quarternary-fill-white hover:border-primary-base focus-within:border-primary-base",
|
|
16943
|
+
error:
|
|
16944
|
+
"border-error-base bg-fill-quarternary-fill-white hover:border-error-base focus-within:border-error-base",
|
|
16945
|
+
warning:
|
|
16946
|
+
"border-warning-base bg-fill-quarternary-fill-white hover:border-warning-base focus-within:border-warning-base",
|
|
16947
|
+
success:
|
|
16948
|
+
"border-success-base bg-fill-quarternary-fill-white hover:border-success-base focus-within:border-success-base",
|
|
16949
|
+
borderless:
|
|
16950
|
+
"border-none shadow-none rounded-0 bg-fill-quarternary-fill-white",
|
|
16951
|
+
inline:
|
|
16952
|
+
"border-transparent shadow-none rounded-0 bg-fill-quarternary-fill-white hover:bg-fill-tertiary-fill-light-gray focus-within:border-transparent focus-within:bg-fill-tertiary-fill-light-gray",
|
|
16953
|
+
sizeDefault: "px-12 py-4",
|
|
16954
|
+
sizeLarge: "px-12 py-6",
|
|
16955
|
+
sizeSmall: "px-12 py-2",
|
|
16956
|
+
};
|
|
16957
|
+
|
|
16958
|
+
function joinClasses() {
|
|
16959
|
+
return Array.prototype.filter.call(arguments, Boolean).join(" ");
|
|
16960
|
+
}
|
|
16961
|
+
|
|
15531
16962
|
function create(config) {
|
|
15532
16963
|
const {
|
|
15533
16964
|
label,
|
|
@@ -15539,7 +16970,14 @@
|
|
|
15539
16970
|
isPrivate = false,
|
|
15540
16971
|
maxFiles = null,
|
|
15541
16972
|
maxFileSize = 10 * 1024 * 1024, // 10MB default
|
|
16973
|
+
disabled = false,
|
|
16974
|
+
variant = "default",
|
|
16975
|
+
inputSize = "default",
|
|
16976
|
+
className = "",
|
|
15542
16977
|
} = config;
|
|
16978
|
+
let disabledState = !!disabled;
|
|
16979
|
+
let currentVariant = variant;
|
|
16980
|
+
let currentInputSize = inputSize;
|
|
15543
16981
|
|
|
15544
16982
|
if (!global.FlowUI) {
|
|
15545
16983
|
throw new Error("FlowUI not available");
|
|
@@ -15557,12 +16995,33 @@
|
|
|
15557
16995
|
|
|
15558
16996
|
// Upload row: button + status + optional end spinner (match Select/MultiSelect trigger)
|
|
15559
16997
|
const uploadWrapper = document.createElement("div");
|
|
15560
|
-
|
|
16998
|
+
var sizeClass =
|
|
16999
|
+
currentInputSize === "large"
|
|
17000
|
+
? UPLOAD_WRAPPER_CLASS.sizeLarge
|
|
17001
|
+
: currentInputSize === "small"
|
|
17002
|
+
? UPLOAD_WRAPPER_CLASS.sizeSmall
|
|
17003
|
+
: UPLOAD_WRAPPER_CLASS.sizeDefault;
|
|
17004
|
+
function applyWrapperClasses() {
|
|
17005
|
+
uploadWrapper.className = joinClasses(
|
|
17006
|
+
UPLOAD_WRAPPER_CLASS.base,
|
|
17007
|
+
UPLOAD_WRAPPER_CLASS[currentVariant] || UPLOAD_WRAPPER_CLASS.default,
|
|
17008
|
+
sizeClass,
|
|
17009
|
+
className
|
|
17010
|
+
);
|
|
17011
|
+
}
|
|
17012
|
+
applyWrapperClasses();
|
|
17013
|
+
uploadWrapper.setAttribute("data-file-input-variant", currentVariant);
|
|
17014
|
+
uploadWrapper.setAttribute("data-file-input-size", currentInputSize);
|
|
17015
|
+
uploadWrapper.setAttribute("data-disabled", disabledState ? "true" : "false");
|
|
15561
17016
|
|
|
15562
17017
|
// Left content (button + status) – pointer-events-none so overlay input receives clicks
|
|
15563
17018
|
const leftContent = document.createElement("div");
|
|
15564
17019
|
leftContent.className = "pointer-events-none flex min-w-0 flex-1 items-center gap-8 truncate";
|
|
15565
17020
|
|
|
17021
|
+
var disabledChildClasses =
|
|
17022
|
+
"group-has-[:disabled]:text-typography-quaternary-text group-has-[:disabled]:bg-fill-tertiary-fill-light-gray group-has-[:disabled]:hover:bg-fill-tertiary-fill-light-gray";
|
|
17023
|
+
var statusTextBaseClass = "text-reg-13 min-w-0 flex-1 truncate";
|
|
17024
|
+
var statusTextDisabledClass = " group-has-[:disabled]:text-typography-quaternary-text";
|
|
15566
17025
|
const useButtonComponent = global.Button && typeof global.Button.create === "function";
|
|
15567
17026
|
const initialButtonText = multiple ? "Choose files" : "Choose a file";
|
|
15568
17027
|
const btn = useButtonComponent
|
|
@@ -15570,31 +17029,41 @@
|
|
|
15570
17029
|
variant: "outline",
|
|
15571
17030
|
size: "small",
|
|
15572
17031
|
text: initialButtonText,
|
|
15573
|
-
className: "shrink-0 truncate",
|
|
17032
|
+
className: "shrink-0 truncate " + disabledChildClasses,
|
|
15574
17033
|
})
|
|
15575
17034
|
: (function () {
|
|
15576
17035
|
const el = document.createElement("div");
|
|
15577
|
-
el.className =
|
|
17036
|
+
el.className =
|
|
17037
|
+
"shrink-0 truncate rounded-2 border-1/2 border-border-primary bg-fill-tertiary-fill-light-gray px-8 py-1 text-reg-13 text-typography-primary-text transition-colors duration-150 hover:bg-fill-secondary-fill-gray " +
|
|
17038
|
+
disabledChildClasses;
|
|
15578
17039
|
el.textContent = initialButtonText;
|
|
15579
17040
|
return el;
|
|
15580
17041
|
})();
|
|
15581
17042
|
|
|
15582
17043
|
// Status text: "No files chosen" (quaternary) or "X file(s) selected"
|
|
15583
17044
|
const statusText = document.createElement("p");
|
|
15584
|
-
statusText.className =
|
|
17045
|
+
statusText.className = statusTextBaseClass + " text-typography-quaternary-text" + statusTextDisabledClass;
|
|
15585
17046
|
|
|
15586
17047
|
// Hidden file input – overlays row, high z-index so it receives clicks
|
|
15587
17048
|
const input = document.createElement("input");
|
|
15588
17049
|
input.type = "file";
|
|
15589
|
-
|
|
17050
|
+
const inputBaseClass = "absolute inset-0 z-10 w-full opacity-0";
|
|
17051
|
+
function applyInputClasses() {
|
|
17052
|
+
input.className =
|
|
17053
|
+
inputBaseClass +
|
|
17054
|
+
(disabledState ? " !pointer-events-none !cursor-not-allowed" : " cursor-pointer");
|
|
17055
|
+
}
|
|
17056
|
+
applyInputClasses();
|
|
15590
17057
|
input.multiple = multiple;
|
|
17058
|
+
input.disabled = disabledState;
|
|
15591
17059
|
if (accept !== "*") {
|
|
15592
17060
|
input.accept = accept;
|
|
15593
17061
|
}
|
|
15594
17062
|
|
|
15595
17063
|
// End icon slot: spinner when uploading (match Select chevron position)
|
|
15596
17064
|
const endIconSlot = document.createElement("div");
|
|
15597
|
-
endIconSlot.className =
|
|
17065
|
+
endIconSlot.className =
|
|
17066
|
+
"ml-4 flex size-16 items-center justify-center shrink-0 text-typography-quaternary-text group-has-[:disabled]:text-typography-quaternary-text";
|
|
15598
17067
|
endIconSlot.style.display = "none";
|
|
15599
17068
|
|
|
15600
17069
|
// Uploaded files: badge list (match UploadedFilePreviewer – flex-wrap gap-2)
|
|
@@ -15775,13 +17244,13 @@
|
|
|
15775
17244
|
|
|
15776
17245
|
if (!filesChosen) {
|
|
15777
17246
|
statusText.textContent = "No files chosen";
|
|
15778
|
-
statusText.className =
|
|
17247
|
+
statusText.className = statusTextBaseClass + " text-typography-quaternary-text" + statusTextDisabledClass;
|
|
15779
17248
|
} else if (uploadingCount > 0) {
|
|
15780
17249
|
statusText.textContent = "Uploading…";
|
|
15781
|
-
statusText.className =
|
|
17250
|
+
statusText.className = statusTextBaseClass + " text-typography-quaternary-text" + statusTextDisabledClass;
|
|
15782
17251
|
} else {
|
|
15783
17252
|
statusText.textContent = `${uploadedCount} file${uploadedCount !== 1 ? "s" : ""} selected`;
|
|
15784
|
-
statusText.className =
|
|
17253
|
+
statusText.className = statusTextBaseClass + " text-typography-primary-text" + statusTextDisabledClass;
|
|
15785
17254
|
}
|
|
15786
17255
|
|
|
15787
17256
|
endIconSlot.style.display = uploadingCount > 0 ? "flex" : "none";
|
|
@@ -15918,6 +17387,32 @@
|
|
|
15918
17387
|
loadExistingFiles();
|
|
15919
17388
|
updateStatus();
|
|
15920
17389
|
|
|
17390
|
+
field.setDisabled = function (d) {
|
|
17391
|
+
disabledState = !!d;
|
|
17392
|
+
input.disabled = disabledState;
|
|
17393
|
+
applyInputClasses();
|
|
17394
|
+
applyWrapperClasses();
|
|
17395
|
+
uploadWrapper.setAttribute("data-disabled", disabledState ? "true" : "false");
|
|
17396
|
+
};
|
|
17397
|
+
|
|
17398
|
+
field.setVariant = function (v) {
|
|
17399
|
+
currentVariant = v || "default";
|
|
17400
|
+
uploadWrapper.setAttribute("data-file-input-variant", currentVariant);
|
|
17401
|
+
applyWrapperClasses();
|
|
17402
|
+
};
|
|
17403
|
+
|
|
17404
|
+
field.setInputSize = function (s) {
|
|
17405
|
+
currentInputSize = s || "default";
|
|
17406
|
+
sizeClass =
|
|
17407
|
+
currentInputSize === "large"
|
|
17408
|
+
? UPLOAD_WRAPPER_CLASS.sizeLarge
|
|
17409
|
+
: currentInputSize === "small"
|
|
17410
|
+
? UPLOAD_WRAPPER_CLASS.sizeSmall
|
|
17411
|
+
: UPLOAD_WRAPPER_CLASS.sizeDefault;
|
|
17412
|
+
uploadWrapper.setAttribute("data-file-input-size", currentInputSize);
|
|
17413
|
+
applyWrapperClasses();
|
|
17414
|
+
};
|
|
17415
|
+
|
|
15921
17416
|
return field;
|
|
15922
17417
|
}
|
|
15923
17418
|
|
|
@@ -15932,7 +17427,7 @@
|
|
|
15932
17427
|
|
|
15933
17428
|
|
|
15934
17429
|
// ============================================
|
|
15935
|
-
// File
|
|
17430
|
+
// File 39/42: components/table.js
|
|
15936
17431
|
// ============================================
|
|
15937
17432
|
|
|
15938
17433
|
/**
|
|
@@ -16273,7 +17768,455 @@
|
|
|
16273
17768
|
|
|
16274
17769
|
|
|
16275
17770
|
// ============================================
|
|
16276
|
-
// File
|
|
17771
|
+
// File 40/42: components/tabs.js
|
|
17772
|
+
// ============================================
|
|
17773
|
+
|
|
17774
|
+
/**
|
|
17775
|
+
* Tabs Component (vanilla JS)
|
|
17776
|
+
* Tabbed interface with list, triggers, and content panels.
|
|
17777
|
+
* Ref: Radix-style Tabs; design tokens match design system.
|
|
17778
|
+
*/
|
|
17779
|
+
|
|
17780
|
+
(function (global) {
|
|
17781
|
+
|
|
17782
|
+
function getComponent(name) {
|
|
17783
|
+
if (typeof global.FlowUI !== "undefined" && typeof global.FlowUI._getComponent === "function") {
|
|
17784
|
+
var c = global.FlowUI._getComponent(name);
|
|
17785
|
+
if (c) return c;
|
|
17786
|
+
}
|
|
17787
|
+
return global[name];
|
|
17788
|
+
}
|
|
17789
|
+
|
|
17790
|
+
var LIST_BASE_CLASS =
|
|
17791
|
+
"inline-flex items-center justify-center gap-2 rounded-4 bg-fill-tertiary-fill-light-gray p-4";
|
|
17792
|
+
|
|
17793
|
+
/** Button variant classes for active (outline) vs inactive (ghost) */
|
|
17794
|
+
var BUTTON_OUTLINE =
|
|
17795
|
+
"shadow-soft-extra-small group bg-fill-quarternary-fill-white border-1/2 border-border-primary text-typography-primary-text hover:bg-fill-tertiary-fill-light-gray active:bg-fill-secondary-fill-gray disabled:opacity-50 disabled:border-fill-secondary-fill-gray";
|
|
17796
|
+
var BUTTON_GHOST =
|
|
17797
|
+
"group text-typography-primary-text hover:bg-fill-tertiary-fill-light-gray active:bg-fill-secondary-fill-gray disabled:text-typography-quaternary-text";
|
|
17798
|
+
var BUTTON_BASE =
|
|
17799
|
+
"inline-flex items-center justify-center whitespace-nowrap !text-med-12 transition-colors disabled:pointer-events-none hover:cursor-pointer h-fit";
|
|
17800
|
+
var BUTTON_SIZES = {
|
|
17801
|
+
default: "px-8 py-4 gap-4 rounded-4",
|
|
17802
|
+
small: "px-8 py-4 gap-4 rounded-4",
|
|
17803
|
+
large: "px-16 py-8 gap-4 rounded-4",
|
|
17804
|
+
};
|
|
17805
|
+
|
|
17806
|
+
var CONTENT_BASE_CLASS =
|
|
17807
|
+
"ring-offset-background focus-visible:ring-ring h-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2";
|
|
17808
|
+
|
|
17809
|
+
function join() {
|
|
17810
|
+
return Array.prototype.filter.call(arguments, Boolean).join(" ");
|
|
17811
|
+
}
|
|
17812
|
+
|
|
17813
|
+
/**
|
|
17814
|
+
* Create a full Tabs component (list + triggers + content panels)
|
|
17815
|
+
* @param {Object} config
|
|
17816
|
+
* @param {string} [config.defaultValue] - initial active tab value
|
|
17817
|
+
* @param {string} [config.value] - controlled active value
|
|
17818
|
+
* @param {Function} [config.onChange] - (value) => void when tab changes
|
|
17819
|
+
* @param {Array<{value: string, label: string, content: HTMLElement|string}>} config.tabs - tab definitions
|
|
17820
|
+
* @param {string} [config.size] - 'default' | 'small' | 'large'
|
|
17821
|
+
* @param {string} [config.listClassName] - extra class on list
|
|
17822
|
+
* @param {string} [config.contentClassName] - extra class on content wrapper
|
|
17823
|
+
* @returns {HTMLElement} root element (wrapper containing list + content area)
|
|
17824
|
+
*/
|
|
17825
|
+
function create(config) {
|
|
17826
|
+
var opts = config || {};
|
|
17827
|
+
var defaultValue = opts.defaultValue;
|
|
17828
|
+
var controlledValue = opts.value;
|
|
17829
|
+
var onChange = opts.onChange;
|
|
17830
|
+
var tabs = opts.tabs || [];
|
|
17831
|
+
var size = opts.size || "default";
|
|
17832
|
+
var listClassName = opts.listClassName || "";
|
|
17833
|
+
var contentClassName = opts.contentClassName || "";
|
|
17834
|
+
|
|
17835
|
+
var sizeClass = BUTTON_SIZES[size] || BUTTON_SIZES.default;
|
|
17836
|
+
|
|
17837
|
+
var root = document.createElement("div");
|
|
17838
|
+
root.className = "tabs-root w-full";
|
|
17839
|
+
|
|
17840
|
+
var activeValue = controlledValue !== undefined ? controlledValue : defaultValue !== undefined ? defaultValue : (tabs[0] && tabs[0].value) || "";
|
|
17841
|
+
|
|
17842
|
+
// List container
|
|
17843
|
+
var list = document.createElement("div");
|
|
17844
|
+
list.setAttribute("role", "tablist");
|
|
17845
|
+
list.className = join(LIST_BASE_CLASS, listClassName);
|
|
17846
|
+
|
|
17847
|
+
// Content container (holds all panels; we show/hide by value)
|
|
17848
|
+
var contentWrapper = document.createElement("div");
|
|
17849
|
+
contentWrapper.className = join("tabs-content-wrapper mt-4", contentClassName);
|
|
17850
|
+
|
|
17851
|
+
var triggerEls = [];
|
|
17852
|
+
var contentPanels = [];
|
|
17853
|
+
|
|
17854
|
+
var Button = getComponent("Button");
|
|
17855
|
+
|
|
17856
|
+
tabs.forEach(function (tab, index) {
|
|
17857
|
+
var value = tab.value;
|
|
17858
|
+
var label = tab.label != null ? tab.label : value;
|
|
17859
|
+
var content = tab.content;
|
|
17860
|
+
|
|
17861
|
+
var isActive = value === activeValue;
|
|
17862
|
+
var trigger = Button.create({
|
|
17863
|
+
variant: isActive ? "outline" : "ghost",
|
|
17864
|
+
size: size === "small" ? "small" : size === "large" ? "large" : "default",
|
|
17865
|
+
text: label,
|
|
17866
|
+
type: "button",
|
|
17867
|
+
className: "mx-2",
|
|
17868
|
+
onClick: function () {
|
|
17869
|
+
if (activeValue === value) return;
|
|
17870
|
+
if (controlledValue === undefined) {
|
|
17871
|
+
activeValue = value;
|
|
17872
|
+
updateActiveState();
|
|
17873
|
+
}
|
|
17874
|
+
if (typeof onChange === "function") {
|
|
17875
|
+
onChange(value);
|
|
17876
|
+
}
|
|
17877
|
+
},
|
|
17878
|
+
});
|
|
17879
|
+
|
|
17880
|
+
trigger.setAttribute("role", "tab");
|
|
17881
|
+
trigger.setAttribute("aria-selected", value === activeValue ? "true" : "false");
|
|
17882
|
+
trigger.setAttribute("data-state", value === activeValue ? "active" : "inactive");
|
|
17883
|
+
trigger.setAttribute("data-value", value);
|
|
17884
|
+
trigger.tabIndex = value === activeValue ? 0 : -1;
|
|
17885
|
+
|
|
17886
|
+
trigger.addEventListener("keydown", function (e) {
|
|
17887
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
17888
|
+
e.preventDefault();
|
|
17889
|
+
trigger.click();
|
|
17890
|
+
}
|
|
17891
|
+
if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
|
|
17892
|
+
e.preventDefault();
|
|
17893
|
+
var nextIndex = e.key === "ArrowRight" ? index + 1 : index - 1;
|
|
17894
|
+
if (nextIndex >= 0 && nextIndex < tabs.length) {
|
|
17895
|
+
var nextTrigger = triggerEls[nextIndex];
|
|
17896
|
+
if (nextTrigger) {
|
|
17897
|
+
nextTrigger.focus();
|
|
17898
|
+
nextTrigger.click();
|
|
17899
|
+
}
|
|
17900
|
+
}
|
|
17901
|
+
}
|
|
17902
|
+
});
|
|
17903
|
+
|
|
17904
|
+
list.appendChild(trigger);
|
|
17905
|
+
triggerEls.push(trigger);
|
|
17906
|
+
|
|
17907
|
+
var panel = document.createElement("div");
|
|
17908
|
+
panel.setAttribute("role", "tabpanel");
|
|
17909
|
+
panel.setAttribute("aria-hidden", value !== activeValue ? "true" : "false");
|
|
17910
|
+
panel.setAttribute("data-value", value);
|
|
17911
|
+
panel.className = join(CONTENT_BASE_CLASS, value !== activeValue ? "hidden" : "");
|
|
17912
|
+
if (typeof content === "string") {
|
|
17913
|
+
panel.innerHTML = content;
|
|
17914
|
+
} else if (content && content.nodeType === 1) {
|
|
17915
|
+
panel.appendChild(content);
|
|
17916
|
+
}
|
|
17917
|
+
contentWrapper.appendChild(panel);
|
|
17918
|
+
contentPanels.push(panel);
|
|
17919
|
+
});
|
|
17920
|
+
|
|
17921
|
+
function updateActiveState() {
|
|
17922
|
+
triggerEls.forEach(function (t, i) {
|
|
17923
|
+
var val = tabs[i] && tabs[i].value;
|
|
17924
|
+
var isActive = val === activeValue;
|
|
17925
|
+
t.setAttribute("aria-selected", isActive ? "true" : "false");
|
|
17926
|
+
t.setAttribute("data-state", isActive ? "active" : "inactive");
|
|
17927
|
+
t.tabIndex = isActive ? 0 : -1;
|
|
17928
|
+
t.className = join(BUTTON_BASE, isActive ? BUTTON_OUTLINE : BUTTON_GHOST, sizeClass, "mx-2");
|
|
17929
|
+
});
|
|
17930
|
+
contentPanels.forEach(function (p, i) {
|
|
17931
|
+
var val = tabs[i] && tabs[i].value;
|
|
17932
|
+
var isActive = val === activeValue;
|
|
17933
|
+
p.setAttribute("aria-hidden", isActive ? "false" : "true");
|
|
17934
|
+
p.classList.toggle("hidden", !isActive);
|
|
17935
|
+
});
|
|
17936
|
+
}
|
|
17937
|
+
|
|
17938
|
+
root.appendChild(list);
|
|
17939
|
+
root.appendChild(contentWrapper);
|
|
17940
|
+
|
|
17941
|
+
root.getValue = function () {
|
|
17942
|
+
return activeValue;
|
|
17943
|
+
};
|
|
17944
|
+
|
|
17945
|
+
root.setValue = function (newValue) {
|
|
17946
|
+
if (newValue === activeValue) return;
|
|
17947
|
+
activeValue = newValue;
|
|
17948
|
+
updateActiveState();
|
|
17949
|
+
};
|
|
17950
|
+
|
|
17951
|
+
return root;
|
|
17952
|
+
}
|
|
17953
|
+
|
|
17954
|
+
var Tabs = {
|
|
17955
|
+
create: create,
|
|
17956
|
+
};
|
|
17957
|
+
|
|
17958
|
+
if (typeof module !== "undefined" && module.exports) {
|
|
17959
|
+
module.exports = Tabs;
|
|
17960
|
+
} else {
|
|
17961
|
+
global.Tabs = Tabs;
|
|
17962
|
+
}
|
|
17963
|
+
})(typeof window !== "undefined" ? window : undefined);
|
|
17964
|
+
|
|
17965
|
+
|
|
17966
|
+
|
|
17967
|
+
// ============================================
|
|
17968
|
+
// File 41/42: components/steps.js
|
|
17969
|
+
// ============================================
|
|
17970
|
+
|
|
17971
|
+
/**
|
|
17972
|
+
* Steps Component (vanilla JS)
|
|
17973
|
+
* Multi-step flow with numbered step triggers and optional content panels.
|
|
17974
|
+
* Use for wizards / step-by-step forms (e.g. "1 Step One", "2 Step Two").
|
|
17975
|
+
*/
|
|
17976
|
+
|
|
17977
|
+
(function (global) {
|
|
17978
|
+
|
|
17979
|
+
function getComponent(name) {
|
|
17980
|
+
if (typeof global.FlowUI !== "undefined" && typeof global.FlowUI._getComponent === "function") {
|
|
17981
|
+
var c = global.FlowUI._getComponent(name);
|
|
17982
|
+
if (c) return c;
|
|
17983
|
+
}
|
|
17984
|
+
return global[name];
|
|
17985
|
+
}
|
|
17986
|
+
|
|
17987
|
+
var LIST_BASE_CLASS =
|
|
17988
|
+
"flex items-center flex-wrap gap-0 rounded-4 border border-border-primary bg-fill-quarternary-fill-white p-4";
|
|
17989
|
+
|
|
17990
|
+
/** Inactive step: muted label color only (button stays ghost large) */
|
|
17991
|
+
var INACTIVE_LABEL_CLASS = "!text-typography-quaternary-text";
|
|
17992
|
+
|
|
17993
|
+
/** Box around step number: active = dark fill + invert text, inactive = dark gray fill + tertiary text */
|
|
17994
|
+
var NUMBER_BOX_ACTIVE =
|
|
17995
|
+
"flex h-16 w-16 items-center justify-center rounded-4 bg-typography-primary-text text-typography-invert-text shrink-0";
|
|
17996
|
+
var NUMBER_BOX_INACTIVE =
|
|
17997
|
+
"flex h-16 w-16 items-center justify-center rounded-4 bg-fill-primary-fill-dark-gray text-typography-tertiary-text shrink-0";
|
|
17998
|
+
|
|
17999
|
+
/** Horizontal line between steps (step1 ——— step2) */
|
|
18000
|
+
var CONNECTOR_CLASS = "flex-1 min-w-12 max-w-32 h-0 border-t border-border-primary shrink-0 mx-2 self-center";
|
|
18001
|
+
|
|
18002
|
+
var CONTENT_BASE_CLASS =
|
|
18003
|
+
"ring-offset-background focus-visible:ring-2 focus-visible:ring-offset-2 h-full";
|
|
18004
|
+
|
|
18005
|
+
function join() {
|
|
18006
|
+
return Array.prototype.filter.call(arguments, Boolean).join(" ");
|
|
18007
|
+
}
|
|
18008
|
+
|
|
18009
|
+
/**
|
|
18010
|
+
* Create a Steps component (numbered step triggers + optional content)
|
|
18011
|
+
* Design: ghost large Button for all steps; inactive steps use muted label color. Connectors between steps. Optional title/description above.
|
|
18012
|
+
* @param {Object} config
|
|
18013
|
+
* @param {Array<{id: string, label: string, content?: HTMLElement|string}>} config.steps - step definitions
|
|
18014
|
+
* @param {string} [config.defaultValue] - initial active step id
|
|
18015
|
+
* @param {string} [config.value] - controlled active step id
|
|
18016
|
+
* @param {Function} [config.onChange] - (stepId) => void when step changes
|
|
18017
|
+
* @param {string} [config.title] - optional title above steps
|
|
18018
|
+
* @param {string} [config.description] - optional description above steps
|
|
18019
|
+
* @param {string} [config.listClassName] - extra class on step list
|
|
18020
|
+
* @param {string} [config.contentClassName] - extra class on content wrapper
|
|
18021
|
+
* @param {boolean} [config.showContent=true] - whether to render content panels (if steps have content)
|
|
18022
|
+
* @returns {HTMLElement} root element
|
|
18023
|
+
*/
|
|
18024
|
+
function create(config) {
|
|
18025
|
+
var opts = config || {};
|
|
18026
|
+
var steps = opts.steps || [];
|
|
18027
|
+
var defaultValue = opts.defaultValue;
|
|
18028
|
+
var controlledValue = opts.value;
|
|
18029
|
+
var onChange = opts.onChange;
|
|
18030
|
+
var title = opts.title;
|
|
18031
|
+
var description = opts.description;
|
|
18032
|
+
var listClassName = opts.listClassName || "";
|
|
18033
|
+
var contentClassName = opts.contentClassName || "";
|
|
18034
|
+
var showContent = opts.showContent !== false;
|
|
18035
|
+
|
|
18036
|
+
var root = document.createElement("div");
|
|
18037
|
+
root.className = "steps-root w-full";
|
|
18038
|
+
|
|
18039
|
+
var activeId =
|
|
18040
|
+
controlledValue !== undefined
|
|
18041
|
+
? controlledValue
|
|
18042
|
+
: defaultValue !== undefined
|
|
18043
|
+
? defaultValue
|
|
18044
|
+
: (steps[0] && steps[0].id) || "";
|
|
18045
|
+
|
|
18046
|
+
if (title != null && title !== "") {
|
|
18047
|
+
var titleEl = document.createElement("h3");
|
|
18048
|
+
titleEl.className = "text-typography-primary-text";
|
|
18049
|
+
titleEl.textContent = title;
|
|
18050
|
+
root.appendChild(titleEl);
|
|
18051
|
+
}
|
|
18052
|
+
if (description != null && description !== "") {
|
|
18053
|
+
var descEl = document.createElement("p");
|
|
18054
|
+
descEl.className = "text-typography-secondary-text";
|
|
18055
|
+
descEl.textContent = description;
|
|
18056
|
+
root.appendChild(descEl);
|
|
18057
|
+
}
|
|
18058
|
+
|
|
18059
|
+
// Step list (horizontal: step, connector, step, connector, ...)
|
|
18060
|
+
var list = document.createElement("div");
|
|
18061
|
+
list.setAttribute("role", "tablist");
|
|
18062
|
+
list.setAttribute("aria-label", "Steps");
|
|
18063
|
+
list.className = join(LIST_BASE_CLASS, listClassName);
|
|
18064
|
+
|
|
18065
|
+
var triggerEls = [];
|
|
18066
|
+
var numberBoxEls = [];
|
|
18067
|
+
var contentPanels = [];
|
|
18068
|
+
var contentWrapper = null;
|
|
18069
|
+
|
|
18070
|
+
if (showContent && steps.some(function (s) { return s.content != null; })) {
|
|
18071
|
+
contentWrapper = document.createElement("div");
|
|
18072
|
+
contentWrapper.className = join("steps-content-wrapper mt-4", contentClassName);
|
|
18073
|
+
}
|
|
18074
|
+
|
|
18075
|
+
var Button = getComponent("Button");
|
|
18076
|
+
|
|
18077
|
+
steps.forEach(function (step, index) {
|
|
18078
|
+
var stepId = step.id;
|
|
18079
|
+
var label = step.label != null ? step.label : stepId;
|
|
18080
|
+
var content = step.content;
|
|
18081
|
+
var stepNumber = index + 1;
|
|
18082
|
+
var isActive = stepId === activeId;
|
|
18083
|
+
|
|
18084
|
+
var trigger = Button.create({
|
|
18085
|
+
variant: "ghost",
|
|
18086
|
+
size: "large",
|
|
18087
|
+
text: "\u00A0",
|
|
18088
|
+
type: "button",
|
|
18089
|
+
className: isActive ? "" : INACTIVE_LABEL_CLASS,
|
|
18090
|
+
onClick: function () {
|
|
18091
|
+
if (activeId === stepId) return;
|
|
18092
|
+
if (controlledValue === undefined) {
|
|
18093
|
+
activeId = stepId;
|
|
18094
|
+
updateActiveState();
|
|
18095
|
+
}
|
|
18096
|
+
if (typeof onChange === "function") {
|
|
18097
|
+
onChange(stepId);
|
|
18098
|
+
}
|
|
18099
|
+
},
|
|
18100
|
+
});
|
|
18101
|
+
|
|
18102
|
+
var numberBox = document.createElement("span");
|
|
18103
|
+
numberBox.setAttribute("aria-hidden", "true");
|
|
18104
|
+
numberBox.className = isActive ? NUMBER_BOX_ACTIVE : NUMBER_BOX_INACTIVE;
|
|
18105
|
+
numberBox.textContent = String(stepNumber);
|
|
18106
|
+
|
|
18107
|
+
trigger.innerHTML = "";
|
|
18108
|
+
trigger.appendChild(numberBox);
|
|
18109
|
+
trigger.appendChild(document.createTextNode(" " + label));
|
|
18110
|
+
|
|
18111
|
+
trigger.setAttribute("role", "tab");
|
|
18112
|
+
trigger.setAttribute("aria-selected", isActive ? "true" : "false");
|
|
18113
|
+
trigger.setAttribute("data-state", isActive ? "active" : "inactive");
|
|
18114
|
+
trigger.setAttribute("data-step-id", stepId);
|
|
18115
|
+
trigger.tabIndex = isActive ? 0 : -1;
|
|
18116
|
+
|
|
18117
|
+
numberBoxEls.push(numberBox);
|
|
18118
|
+
|
|
18119
|
+
trigger.addEventListener("keydown", function (e) {
|
|
18120
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
18121
|
+
e.preventDefault();
|
|
18122
|
+
trigger.click();
|
|
18123
|
+
}
|
|
18124
|
+
if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
|
|
18125
|
+
e.preventDefault();
|
|
18126
|
+
var nextIndex = e.key === "ArrowRight" ? index + 1 : index - 1;
|
|
18127
|
+
if (nextIndex >= 0 && nextIndex < steps.length) {
|
|
18128
|
+
var nextTrigger = triggerEls[nextIndex];
|
|
18129
|
+
if (nextTrigger) {
|
|
18130
|
+
nextTrigger.focus();
|
|
18131
|
+
nextTrigger.click();
|
|
18132
|
+
}
|
|
18133
|
+
}
|
|
18134
|
+
}
|
|
18135
|
+
});
|
|
18136
|
+
|
|
18137
|
+
list.appendChild(trigger);
|
|
18138
|
+
triggerEls.push(trigger);
|
|
18139
|
+
|
|
18140
|
+
if (index < steps.length - 1) {
|
|
18141
|
+
var connector = document.createElement("span");
|
|
18142
|
+
connector.className = CONNECTOR_CLASS;
|
|
18143
|
+
connector.setAttribute("aria-hidden", "true");
|
|
18144
|
+
list.appendChild(connector);
|
|
18145
|
+
}
|
|
18146
|
+
|
|
18147
|
+
if (contentWrapper && content != null) {
|
|
18148
|
+
var panel = document.createElement("div");
|
|
18149
|
+
panel.setAttribute("role", "tabpanel");
|
|
18150
|
+
panel.setAttribute("aria-hidden", stepId !== activeId ? "true" : "false");
|
|
18151
|
+
panel.setAttribute("data-step-id", stepId);
|
|
18152
|
+
panel.className = join(CONTENT_BASE_CLASS, stepId !== activeId ? "hidden" : "");
|
|
18153
|
+
if (typeof content === "string") {
|
|
18154
|
+
panel.innerHTML = content;
|
|
18155
|
+
} else if (content && content.nodeType === 1) {
|
|
18156
|
+
panel.appendChild(content);
|
|
18157
|
+
}
|
|
18158
|
+
contentWrapper.appendChild(panel);
|
|
18159
|
+
contentPanels.push(panel);
|
|
18160
|
+
}
|
|
18161
|
+
});
|
|
18162
|
+
|
|
18163
|
+
function updateActiveState() {
|
|
18164
|
+
triggerEls.forEach(function (t, i) {
|
|
18165
|
+
var step = steps[i];
|
|
18166
|
+
var id = step && step.id;
|
|
18167
|
+
var isActive = id === activeId;
|
|
18168
|
+
t.setAttribute("aria-selected", isActive ? "true" : "false");
|
|
18169
|
+
t.setAttribute("data-state", isActive ? "active" : "inactive");
|
|
18170
|
+
t.tabIndex = isActive ? 0 : -1;
|
|
18171
|
+
if (isActive) {
|
|
18172
|
+
t.classList.remove(INACTIVE_LABEL_CLASS);
|
|
18173
|
+
} else {
|
|
18174
|
+
t.classList.add(INACTIVE_LABEL_CLASS);
|
|
18175
|
+
}
|
|
18176
|
+
numberBoxEls[i].className = isActive ? NUMBER_BOX_ACTIVE : NUMBER_BOX_INACTIVE;
|
|
18177
|
+
});
|
|
18178
|
+
contentPanels.forEach(function (p, i) {
|
|
18179
|
+
var step = steps[i];
|
|
18180
|
+
var id = step && step.id;
|
|
18181
|
+
var isActive = id === activeId;
|
|
18182
|
+
p.setAttribute("aria-hidden", isActive ? "false" : "true");
|
|
18183
|
+
p.classList.toggle("hidden", !isActive);
|
|
18184
|
+
});
|
|
18185
|
+
}
|
|
18186
|
+
|
|
18187
|
+
root.appendChild(list);
|
|
18188
|
+
if (contentWrapper) {
|
|
18189
|
+
root.appendChild(contentWrapper);
|
|
18190
|
+
}
|
|
18191
|
+
|
|
18192
|
+
root.getValue = function () {
|
|
18193
|
+
return activeId;
|
|
18194
|
+
};
|
|
18195
|
+
|
|
18196
|
+
root.setValue = function (newId) {
|
|
18197
|
+
if (newId === activeId) return;
|
|
18198
|
+
activeId = newId;
|
|
18199
|
+
updateActiveState();
|
|
18200
|
+
};
|
|
18201
|
+
|
|
18202
|
+
return root;
|
|
18203
|
+
}
|
|
18204
|
+
|
|
18205
|
+
var Steps = {
|
|
18206
|
+
create: create,
|
|
18207
|
+
};
|
|
18208
|
+
|
|
18209
|
+
if (typeof module !== "undefined" && module.exports) {
|
|
18210
|
+
module.exports = Steps;
|
|
18211
|
+
} else {
|
|
18212
|
+
global.Steps = Steps;
|
|
18213
|
+
}
|
|
18214
|
+
})(typeof window !== "undefined" ? window : undefined);
|
|
18215
|
+
|
|
18216
|
+
|
|
18217
|
+
|
|
18218
|
+
// ============================================
|
|
18219
|
+
// File 42/42: index.js
|
|
16277
18220
|
// ============================================
|
|
16278
18221
|
|
|
16279
18222
|
/**
|
|
@@ -16349,6 +18292,7 @@
|
|
|
16349
18292
|
require("./components/input.js");
|
|
16350
18293
|
require("./components/currency.js");
|
|
16351
18294
|
require("./components/textarea.js");
|
|
18295
|
+
require("./components/richtext-editor.js");
|
|
16352
18296
|
require("./components/duration/duration-utils.js");
|
|
16353
18297
|
require("./components/duration/duration-constants.js");
|
|
16354
18298
|
require("./components/duration/duration.js");
|
|
@@ -16364,8 +18308,12 @@
|
|
|
16364
18308
|
require("./components/phone-input/phone-utils.js");
|
|
16365
18309
|
require("./components/phone-input/phone-input.js");
|
|
16366
18310
|
require("./components/checkbox.js");
|
|
18311
|
+
require("./components/checkbox-group.js");
|
|
16367
18312
|
require("./components/radio-group.js");
|
|
18313
|
+
require("./components/card-select.js");
|
|
16368
18314
|
require("./components/table.js");
|
|
18315
|
+
require("./components/tabs.js");
|
|
18316
|
+
require("./components/steps.js");
|
|
16369
18317
|
|
|
16370
18318
|
// Export FlowUI and SuperLeap from global scope
|
|
16371
18319
|
if (typeof global !== "undefined" && global.FlowUI) {
|
|
@@ -16376,6 +18324,7 @@
|
|
|
16376
18324
|
getSdk: global.superleapClient.getSdk,
|
|
16377
18325
|
isAvailable: global.superleapClient.isAvailable,
|
|
16378
18326
|
getDefaultConfig: global.superleapClient.getDefaultConfig,
|
|
18327
|
+
getBaseUrl: global.superleapClient.getBaseUrl,
|
|
16379
18328
|
}
|
|
16380
18329
|
: null;
|
|
16381
18330
|
|
|
@@ -16391,6 +18340,7 @@
|
|
|
16391
18340
|
getSdk: window.superleapClient.getSdk,
|
|
16392
18341
|
isAvailable: window.superleapClient.isAvailable,
|
|
16393
18342
|
getDefaultConfig: window.superleapClient.getDefaultConfig,
|
|
18343
|
+
getBaseUrl: window.superleapClient.getBaseUrl,
|
|
16394
18344
|
}
|
|
16395
18345
|
: null;
|
|
16396
18346
|
|
|
@@ -16426,6 +18376,7 @@
|
|
|
16426
18376
|
"InputComponent",
|
|
16427
18377
|
"CurrencyComponent",
|
|
16428
18378
|
"TextareaComponent",
|
|
18379
|
+
"RichTextEditorComponent",
|
|
16429
18380
|
"Duration",
|
|
16430
18381
|
"DateTimePicker",
|
|
16431
18382
|
"Enumeration",
|
|
@@ -16437,8 +18388,12 @@
|
|
|
16437
18388
|
"FileInput",
|
|
16438
18389
|
"PhoneInput",
|
|
16439
18390
|
"Checkbox",
|
|
18391
|
+
"CheckboxGroup",
|
|
16440
18392
|
"RadioGroup",
|
|
18393
|
+
"CardSelect",
|
|
16441
18394
|
"SuperleapTable",
|
|
18395
|
+
"Tabs",
|
|
18396
|
+
"Steps",
|
|
16442
18397
|
];
|
|
16443
18398
|
|
|
16444
18399
|
componentNames.forEach((name) => {
|
|
@@ -16468,6 +18423,7 @@
|
|
|
16468
18423
|
getSdk: client.getSdk.bind(client),
|
|
16469
18424
|
isAvailable: client.isAvailable.bind(client),
|
|
16470
18425
|
getDefaultConfig: client.getDefaultConfig.bind(client),
|
|
18426
|
+
getBaseUrl: client.getBaseUrl.bind(client),
|
|
16471
18427
|
// Bridge methods (from crm.js)
|
|
16472
18428
|
connect: client.connect ? client.connect.bind(client) : undefined,
|
|
16473
18429
|
isConnected: client.isConnected
|
|
@@ -16526,7 +18482,7 @@
|
|
|
16526
18482
|
},
|
|
16527
18483
|
});
|
|
16528
18484
|
document.dispatchEvent(event);
|
|
16529
|
-
console.log("[Superleap-Flow] Library ready - v2.3
|
|
18485
|
+
console.log("[Superleap-Flow] Library ready - v2.5.3");
|
|
16530
18486
|
}
|
|
16531
18487
|
|
|
16532
18488
|
// Wait for DOM to be ready before dispatching event
|