obsidian-dev-utils 88.5.0 → 88.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26787,6 +26787,7 @@ init_error();
26787
26787
  init_function();
26788
26788
  var ComponentEx = class _ComponentEx extends import_obsidian99.Component {
26789
26789
  childrenSet = /* @__PURE__ */ new Set();
26790
+ hasBeenLoaded = false;
26790
26791
  loadErrors = [];
26791
26792
  loadPromise = null;
26792
26793
  /**
@@ -26796,11 +26797,21 @@ var ComponentEx = class _ComponentEx extends import_obsidian99.Component {
26796
26797
  * immediately, so `child._loaded` is set before this method returns even when this component has async load logic.
26797
26798
  * The child's async tail (if any) is sequenced into the load promise so a later {@link loadWithPromises} call awaits it.
26798
26799
  *
26800
+ * Adding a child BEFORE the first load is legitimate: the child is queued and loaded when this component loads.
26801
+ * Adding one AFTER this component has been unloaded is not — the child would never be loaded and never unloaded
26802
+ * (a leak), so it is refused with a {@link SilentError}. The typical source of such a call is an `async` method
26803
+ * that was suspended on an `await` when the component got unloaded and then resumed on the dead component; the
26804
+ * {@link SilentError} unwinds it quietly (see {@link isUnloaded}).
26805
+ *
26799
26806
  * @typeParam TComponent - The type of component to add.
26800
26807
  * @param component - The component instance to add.
26801
26808
  * @returns The added component.
26809
+ * @throws A {@link SilentError} if the component has already been unloaded.
26802
26810
  */
26803
26811
  addChild(component) {
26812
+ if (this.isUnloaded()) {
26813
+ throw new SilentError("Component is already unloaded");
26814
+ }
26804
26815
  this._children.push(component);
26805
26816
  this.childrenSet.add(component);
26806
26817
  if (this._loaded) {
@@ -26818,6 +26829,7 @@ var ComponentEx = class _ComponentEx extends import_obsidian99.Component {
26818
26829
  return;
26819
26830
  }
26820
26831
  this._loaded = true;
26832
+ this.hasBeenLoaded = true;
26821
26833
  this.resetLoadState();
26822
26834
  this.onload();
26823
26835
  const onloadAsyncPromise = this.onloadAsync();
@@ -26908,12 +26920,22 @@ var ComponentEx = class _ComponentEx extends import_obsidian99.Component {
26908
26920
  * {@link Component.unload} is a no-op while the component is not loaded, so any teardown registered beforehand would
26909
26921
  * never run if the component is unloaded without first being loaded.
26910
26922
  *
26911
- * @throws An {@link Error} if the component is not loaded.
26923
+ * The two not-loaded cases are deliberately distinguished. A component that was NEVER loaded is a genuine
26924
+ * programming error, so it throws a loud {@link Error}. A component that has ALREADY been unloaded is not —
26925
+ * it is the expected outcome of work that outlived its component (e.g. an `async` method suspended on an
26926
+ * `await` while the component was unloaded, then resumed) — so it throws a {@link SilentError}, which
26927
+ * `handleSilentError` suppresses, letting such work unwind quietly instead of reporting an async error.
26928
+ *
26929
+ * @throws An {@link Error} if the component was never loaded, or a {@link SilentError} if it has already been unloaded.
26912
26930
  */
26913
26931
  ensureLoaded() {
26914
- if (!this._loaded) {
26915
- throw new Error("Component is not loaded");
26932
+ if (this._loaded) {
26933
+ return;
26916
26934
  }
26935
+ if (this.isUnloaded()) {
26936
+ throw new SilentError("Component is already unloaded");
26937
+ }
26938
+ throw new Error("Component is not loaded");
26917
26939
  }
26918
26940
  /**
26919
26941
  * Returns the component's in-flight load {@link Promise} (its {@link onloadAsync} plus children), or `null` when
@@ -26942,6 +26964,22 @@ var ComponentEx = class _ComponentEx extends import_obsidian99.Component {
26942
26964
  hasLoadErrors() {
26943
26965
  return this.loadErrors.length > 0;
26944
26966
  }
26967
+ /**
26968
+ * Returns whether the component has already been unloaded, as opposed to simply not having been loaded yet.
26969
+ *
26970
+ * Both states leave `_loaded` false, but they mean opposite things: a component that was never loaded is still
26971
+ * ahead of its lifecycle (queueing children before load is legitimate), while an unloaded one is behind it and
26972
+ * must not be used any further. The distinction is tracked by a flag set in {@link load}, NOT by an
26973
+ * {@link Component.onunload} override, because subclasses override `onunload` and may not call `super`.
26974
+ *
26975
+ * Use it in a long-running `async` method to abandon work whose component was unloaded mid-flight, when
26976
+ * unwinding via the {@link SilentError} thrown by {@link ensureLoaded} / {@link addChild} is not desired.
26977
+ *
26978
+ * @returns `true` if the component was loaded at some point and is currently unloaded, otherwise `false`.
26979
+ */
26980
+ isUnloaded() {
26981
+ return this.hasBeenLoaded && !this._loaded;
26982
+ }
26945
26983
  /**
26946
26984
  * Sequences an already-started load step into the load promise.
26947
26985
  *
@@ -34123,7 +34161,7 @@ __export(plugin_settings_tab_exports, {
34123
34161
  PluginSettingsTabBase: () => PluginSettingsTabBase,
34124
34162
  SAVE_TO_FILE_CONTEXT: () => SAVE_TO_FILE_CONTEXT
34125
34163
  });
34126
- var import_obsidian132 = require("obsidian");
34164
+ var import_obsidian146 = require("obsidian");
34127
34165
  init_async_events();
34128
34166
  init_function();
34129
34167
  init_type_guards();
@@ -34286,910 +34324,917 @@ function isValidatorComponent(obj) {
34286
34324
  return typeof obj === "object" && obj !== null && "validatorEl" in obj && !!obj.validatorEl;
34287
34325
  }
34288
34326
 
34289
- // src/obsidian/validation.ts
34290
- var validation_exports = {};
34291
- __export(validation_exports, {
34292
- OBSIDIAN_UNSAFE_FILENAME_CHARS: () => OBSIDIAN_UNSAFE_FILENAME_CHARS,
34293
- UNIX_UNSAFE_PATH_CHARS: () => UNIX_UNSAFE_PATH_CHARS,
34294
- WINDOWS_UNSAFE_PATH_CHARS: () => WINDOWS_UNSAFE_PATH_CHARS,
34295
- getOsAndObsidianUnsafePathCharsRegExp: () => getOsAndObsidianUnsafePathCharsRegExp,
34296
- getOsUnsafePathCharsRegExp: () => getOsUnsafePathCharsRegExp,
34297
- isValidationMessageHolder: () => isValidationMessageHolder
34327
+ // src/obsidian/setting-ex.ts
34328
+ var setting_ex_exports = {};
34329
+ __export(setting_ex_exports, {
34330
+ SettingEx: () => SettingEx,
34331
+ adoptSettingEx: () => adoptSettingEx
34332
+ });
34333
+ var import_obsidian144 = require("obsidian");
34334
+
34335
+ // src/obsidian/setting-components/checkbox-component.ts
34336
+ var checkbox_component_exports = {};
34337
+ __export(checkbox_component_exports, {
34338
+ CheckboxComponent: () => CheckboxComponent
34298
34339
  });
34299
34340
  var import_obsidian131 = require("obsidian");
34300
- init_reg_exp();
34301
- function isValidationMessageHolder(value) {
34302
- return value.validationMessage !== void 0;
34303
- }
34304
- var OBSIDIAN_UNSAFE_FILENAME_CHARS = /[#^[\]|]/g;
34305
- var WINDOWS_UNSAFE_PATH_CHARS = /[*\\/<>:|?"]/g;
34306
- var UNIX_UNSAFE_PATH_CHARS = /[\0/]/g;
34307
- function getOsAndObsidianUnsafePathCharsRegExp(isWindows) {
34308
- return oneOf([
34309
- getOsUnsafePathCharsRegExp(isWindows),
34310
- OBSIDIAN_UNSAFE_FILENAME_CHARS
34311
- ]);
34312
- }
34313
- function getOsUnsafePathCharsRegExp(isWindows) {
34314
- isWindows ??= import_obsidian131.Platform.isWin;
34315
- return isWindows ? WINDOWS_UNSAFE_PATH_CHARS : UNIX_UNSAFE_PATH_CHARS;
34316
- }
34341
+ init_css_class();
34342
+ init_plugin_context();
34343
+ var CheckboxComponent = class extends import_obsidian131.ValueComponent {
34344
+ /**
34345
+ * An input element of the checkbox.
34346
+ */
34347
+ inputEl;
34348
+ /**
34349
+ * A validator element of the checkbox.
34350
+ *
34351
+ * @returns The validator element.
34352
+ */
34353
+ get validatorEl() {
34354
+ return this.inputEl;
34355
+ }
34356
+ changeCallback;
34357
+ /**
34358
+ * Creates a new checkbox component.
34359
+ *
34360
+ * @param containerEl - The container element.
34361
+ */
34362
+ constructor(containerEl) {
34363
+ super();
34364
+ addPluginCssClasses(containerEl, ["checkbox-component" /* CheckboxComponent */]);
34365
+ this.inputEl = containerEl.createEl("input", { type: "checkbox" });
34366
+ this.inputEl.addEventListener("change", this.onChanged.bind(this));
34367
+ }
34368
+ /**
34369
+ * Gets the value of the checkbox.
34370
+ *
34371
+ * @returns The value of the checkbox.
34372
+ */
34373
+ getValue() {
34374
+ return this.inputEl.checked;
34375
+ }
34376
+ /**
34377
+ * Sets the callback to be called when the checkbox is changed.
34378
+ *
34379
+ * @param callback - The callback to be called when the checkbox is changed.
34380
+ * @returns The component.
34381
+ */
34382
+ onChange(callback) {
34383
+ this.changeCallback = callback;
34384
+ return this;
34385
+ }
34386
+ /**
34387
+ * Called when the checkbox is changed.
34388
+ */
34389
+ onChanged() {
34390
+ this.changeCallback?.(this.getValue());
34391
+ }
34392
+ /**
34393
+ * Sets the disabled state of the checkbox.
34394
+ *
34395
+ * @param disabled - The disabled state of the checkbox.
34396
+ * @returns The component.
34397
+ */
34398
+ setDisabled(disabled) {
34399
+ super.setDisabled(disabled);
34400
+ this.inputEl.disabled = disabled;
34401
+ return this;
34402
+ }
34403
+ /**
34404
+ * Sets the value of the checkbox.
34405
+ *
34406
+ * @param value - The value to set the checkbox to.
34407
+ * @returns The component.
34408
+ */
34409
+ setValue(value) {
34410
+ this.inputEl.checked = value;
34411
+ return this;
34412
+ }
34413
+ };
34317
34414
 
34318
- // src/obsidian/plugin/plugin-settings-tab.ts
34415
+ // src/obsidian/setting-components/code-highlighter-component.ts
34416
+ var code_highlighter_component_exports = {};
34417
+ __export(code_highlighter_component_exports, {
34418
+ CodeHighlighterComponent: () => CodeHighlighterComponent
34419
+ });
34420
+ var import_obsidian132 = require("obsidian");
34421
+ init_css_class();
34319
34422
  init_plugin_context();
34320
- var SAVE_TO_FILE_CONTEXT = "PluginSettingsTab";
34321
- var PluginSettingsTabBase = class extends mixinAsyncEvents()(import_obsidian132.PluginSettingTab) {
34423
+ var CodeHighlighterComponent = class extends import_obsidian132.ValueComponent {
34322
34424
  /**
34323
- * Whether the plugin settings tab is open.
34425
+ * An input element of the component.
34324
34426
  *
34325
- * @returns Whether the plugin settings tab is open.
34427
+ * @returns The input element of the component.
34326
34428
  */
34327
- get isOpen() {
34328
- return this._isOpen;
34429
+ get inputEl() {
34430
+ return this.textAreaComponent.inputEl;
34329
34431
  }
34330
34432
  /**
34331
- * The settings manager.
34433
+ * Gets the validator element of the component.
34434
+ *
34435
+ * @returns The validator element of the component.
34332
34436
  */
34333
- pluginSettingsComponent;
34437
+ get validatorEl() {
34438
+ return this.inputEl;
34439
+ }
34334
34440
  /**
34335
- * A debounce timeout for saving settings.
34441
+ * The `<code>` element that renders the syntax-highlighted overlay. Subclasses customizing the highlighting can target it.
34442
+ */
34443
+ codeEl;
34444
+ /**
34445
+ * The `<pre>` element that wraps the highlighted code overlay. Subclasses customizing the highlighting can target it.
34446
+ */
34447
+ preEl;
34448
+ /**
34449
+ * The inner text area component.
34450
+ */
34451
+ textAreaComponent;
34452
+ placeholder = "";
34453
+ simulateChangeCallback;
34454
+ tabSize;
34455
+ /**
34456
+ * Creates a new multiple text component.
34336
34457
  *
34337
- * @returns The debounce timeout for saving settings.
34458
+ * @param containerEl - The container element of the component.
34338
34459
  */
34339
- get saveSettingsDebounceTimeoutInMilliseconds() {
34340
- const DEFAULT = 2e3;
34341
- return DEFAULT;
34460
+ constructor(containerEl) {
34461
+ super();
34462
+ addPluginCssClasses(containerEl, "code-highlighter-component" /* CodeHighlighterComponent */);
34463
+ const wrapper = containerEl.createDiv();
34464
+ addPluginCssClasses(wrapper, "setting-component-wrapper" /* SettingComponentWrapper */);
34465
+ this.textAreaComponent = new import_obsidian132.TextAreaComponent(wrapper);
34466
+ this.preEl = wrapper.createEl("pre", {
34467
+ attr: {
34468
+ tabIndex: "-1"
34469
+ }
34470
+ });
34471
+ this.codeEl = this.preEl.createEl("code", {
34472
+ attr: {
34473
+ tabIndex: "-1"
34474
+ }
34475
+ });
34476
+ this.inputEl.addEventListener("input", convertAsyncToSync(this.updateHighlightedCode.bind(this)));
34477
+ this.inputEl.addEventListener("scroll", this.handleScroll.bind(this));
34478
+ this.inputEl.addEventListener("keydown", this.handleKeyDown.bind(this));
34479
+ const DEFAULT_TAB_SIZE = 2;
34480
+ this.tabSize = DEFAULT_TAB_SIZE;
34342
34481
  }
34343
- _isOpen = false;
34344
- component;
34345
- saveSettingsDebounced;
34346
- get pluginSettings() {
34347
- return this.pluginSettingsComponent.settingsState.inputValues;
34482
+ /**
34483
+ * Empties the component.
34484
+ */
34485
+ empty() {
34486
+ this.setValue("");
34348
34487
  }
34349
34488
  /**
34350
- * Creates a new plugin settings tab.
34489
+ * Gets the value of the component.
34351
34490
  *
34352
- * @param params - The params.
34491
+ * @returns The value of the component.
34353
34492
  */
34354
- constructor(params) {
34355
- super(params.plugin.app, params.plugin);
34356
- this.pluginSettingsComponent = params.pluginSettingsComponent;
34357
- addPluginCssClasses(this.containerEl, "plugin-settings-tab" /* PluginSettingsTab */);
34358
- this.saveSettingsDebounced = (0, import_obsidian132.debounce)(
34359
- convertAsyncToSync(() => this.pluginSettingsComponent.saveToFile(SAVE_TO_FILE_CONTEXT)),
34360
- this.saveSettingsDebounceTimeoutInMilliseconds
34361
- );
34362
- this.component = new ComponentEx();
34493
+ getValue() {
34494
+ return this.textAreaComponent.getValue();
34363
34495
  }
34364
34496
  /**
34365
- * Binds a value component to a plugin setting.
34497
+ * Checks if the component is empty.
34366
34498
  *
34367
- * @typeParam UIValue - The type of the value of the UI component.
34368
- * @typeParam TValueComponent - The type of the value component.
34369
- * @typeParam PropertyName - The property name of the plugin settings to bind to.
34370
- * @param params - The params for binding the value component.
34371
- * @returns The value component.
34499
+ * @returns `true` if the component is empty, `false` otherwise.
34372
34500
  */
34373
- bind(params) {
34374
- const {
34375
- propertyName,
34376
- valueComponent,
34377
- ...options
34378
- } = params;
34379
- const DEFAULT_OPTIONS = {
34380
- componentToPluginSettingsValueConverter: (value) => value,
34381
- onChanged: noop,
34382
- pluginSettingsToComponentValueConverter: (value) => value,
34383
- shouldResetSettingWhenComponentIsEmpty: true,
34384
- shouldShowPlaceholderForDefaultValues: true,
34385
- shouldShowValidationMessage: true
34501
+ isEmpty() {
34502
+ return this.textAreaComponent.getValue() === "";
34503
+ }
34504
+ /**
34505
+ * Adds a change listener to the component.
34506
+ *
34507
+ * @param callback - The callback to call when the value changes.
34508
+ * @returns The component.
34509
+ */
34510
+ onChange(callback) {
34511
+ const changeHandler = () => {
34512
+ callback(this.getValue());
34386
34513
  };
34387
- const optionsExt = { ...DEFAULT_OPTIONS, ...options };
34388
- const validatorEl = getValidatorComponent(valueComponent)?.validatorEl;
34389
- const textBasedComponent = getTextBasedComponentValue(valueComponent);
34390
- const readonlyValue = this.getPluginSettingsProperty(propertyName);
34391
- const defaults = this.pluginSettingsComponent.defaultSettings;
34392
- const defaultValue = defaults[propertyName];
34393
- const defaultComponentValue = optionsExt.pluginSettingsToComponentValueConverter(defaultValue);
34394
- textBasedComponent?.setPlaceholderValue(defaultComponentValue);
34395
- let validationMessage;
34396
- let tooltipEl = null;
34397
- let tooltipContentEl = null;
34398
- if (validatorEl) {
34399
- const wrapper = ensureWrapped(validatorEl);
34400
- tooltipEl = wrapper.createDiv();
34401
- addPluginCssClasses(tooltipEl, ["tooltip" /* Tooltip */, "tooltip-validator" /* TooltipValidator */]);
34402
- tooltipContentEl = tooltipEl.createSpan();
34403
- const tooltipArrowEl = tooltipEl.createDiv();
34404
- addPluginCssClasses(tooltipArrowEl, "tooltip-arrow" /* TooltipArrow */);
34405
- tooltipEl.hide();
34406
- wrapper.appendChild(tooltipEl);
34407
- }
34408
- registerAsyncEvent(
34409
- this.component,
34410
- this.on("validationMessageChanged", (anotherPropertyName, anotherValidationMessage) => {
34411
- if (propertyName !== anotherPropertyName) {
34412
- return;
34413
- }
34414
- validationMessage = anotherValidationMessage;
34415
- updateValidatorElDebounced();
34416
- })
34417
- );
34418
- let shouldEmptyOnBlur = false;
34419
- let shouldRevertToDefaultValueOnBlur = false;
34420
- if (textBasedComponent && optionsExt.shouldShowPlaceholderForDefaultValues && deepEqual(readonlyValue, defaultValue)) {
34421
- textBasedComponent.empty();
34422
- } else {
34423
- valueComponent.setValue(optionsExt.pluginSettingsToComponentValueConverter(readonlyValue));
34424
- }
34425
- let shouldSkipOnChange = false;
34426
- const UPDATE_VALIDATOR_EL_TIMEOUT_IN_MILLISECONDS = 100;
34427
- const updateValidatorElDebounced = (0, import_obsidian132.debounce)(() => {
34428
- window.requestAnimationFrame(() => {
34429
- updateValidatorEl();
34430
- });
34431
- }, UPDATE_VALIDATOR_EL_TIMEOUT_IN_MILLISECONDS);
34432
- valueComponent.onChange(convertAsyncToSync(async (uiValue) => {
34433
- if (shouldSkipOnChange) {
34434
- shouldSkipOnChange = false;
34435
- return;
34436
- }
34437
- shouldEmptyOnBlur = false;
34438
- const oldValue = this.getPluginSettingsProperty(propertyName);
34439
- let newValue = void 0;
34440
- let shouldSetProperty = true;
34441
- shouldRevertToDefaultValueOnBlur = !!textBasedComponent?.isEmpty() && optionsExt.shouldResetSettingWhenComponentIsEmpty;
34442
- if (shouldRevertToDefaultValueOnBlur) {
34443
- newValue = defaultValue;
34444
- } else {
34445
- const convertedValue = optionsExt.componentToPluginSettingsValueConverter(uiValue);
34446
- if (isValidationMessageHolder(convertedValue)) {
34447
- validationMessage = convertedValue.validationMessage;
34448
- shouldSetProperty = false;
34449
- } else {
34450
- newValue = convertedValue;
34451
- }
34452
- }
34453
- if (shouldSetProperty) {
34454
- validationMessage = await this.pluginSettingsComponent.setProperty(propertyName, newValue);
34455
- if (textBasedComponent && optionsExt.shouldShowPlaceholderForDefaultValues && !textBasedComponent.isEmpty() && deepEqual(newValue, defaultValue)) {
34456
- shouldEmptyOnBlur = true;
34457
- }
34458
- }
34459
- updateValidatorElDebounced();
34460
- if (shouldSetProperty) {
34461
- await optionsExt.onChanged(newValue, oldValue);
34462
- }
34463
- this.saveSettingsDebounced();
34464
- }));
34465
- validatorEl?.addEventListener("focus", () => {
34466
- updateValidatorElDebounced();
34467
- });
34468
- validatorEl?.addEventListener("blur", () => {
34469
- updateValidatorElDebounced();
34470
- });
34471
- validatorEl?.addEventListener("click", () => {
34472
- window.requestAnimationFrame(() => {
34473
- updateValidatorElDebounced();
34474
- });
34475
- });
34476
- const validationMessages = this.pluginSettingsComponent.settingsState.validationMessages;
34477
- validationMessage = validationMessages[propertyName] ?? "";
34478
- updateValidatorElDebounced();
34479
- return valueComponent;
34480
- function updateValidatorEl() {
34481
- if (!validatorEl?.isActiveElement()) {
34482
- if (shouldEmptyOnBlur) {
34483
- shouldEmptyOnBlur = false;
34484
- if (!textBasedComponent?.isEmpty()) {
34485
- shouldSkipOnChange = true;
34486
- textBasedComponent?.empty();
34487
- }
34488
- } else if (shouldRevertToDefaultValueOnBlur) {
34489
- shouldRevertToDefaultValueOnBlur = false;
34490
- if (textBasedComponent?.isEmpty()) {
34491
- shouldSkipOnChange = true;
34492
- valueComponent.setValue(defaultComponentValue);
34493
- }
34494
- }
34495
- }
34496
- if (!validatorEl) {
34497
- return;
34498
- }
34499
- assertNonNullable(tooltipContentEl);
34500
- if (validationMessage === "") {
34501
- validatorEl.setCustomValidity("");
34502
- validatorEl.checkValidity();
34503
- validationMessage = validatorEl.validationMessage;
34504
- }
34505
- validatorEl.setCustomValidity(validationMessage);
34506
- if (optionsExt.shouldShowValidationMessage) {
34507
- tooltipContentEl.textContent = validationMessage;
34508
- tooltipEl?.toggle(!!validationMessage);
34509
- } else if (validationMessage) {
34510
- (0, import_obsidian132.setTooltip)(validatorEl, validationMessage);
34511
- }
34512
- }
34513
- }
34514
- /**
34515
- * Renders the plugin settings tab.
34516
- */
34517
- display() {
34518
- this.displayLegacy();
34514
+ this.simulateChangeCallback = changeHandler;
34515
+ this.textAreaComponent.onChange(changeHandler);
34516
+ return this;
34519
34517
  }
34520
34518
  /**
34521
- * Legacy way to render the plugin settings tab.
34519
+ * Sets the disabled state of the component.
34522
34520
  *
34523
- * Temporary workaround to avoid dealing with `@deprecated`.
34524
- */
34525
- displayLegacy() {
34526
- this.containerEl.empty();
34527
- this._isOpen = true;
34528
- this.component.load();
34529
- registerAsyncEvent(this.component, this.pluginSettingsComponent.on("loadSettings", this.onLoadSettings.bind(this)));
34530
- registerAsyncEvent(this.component, this.pluginSettingsComponent.on("saveSettings", (newState, oldState, context) => this.onSaveSettings({ context, newState, oldState })));
34531
- }
34532
- /**
34533
- * Hides the plugin settings tab.
34521
+ * @param disabled - The disabled state to set.
34522
+ * @returns The component.
34534
34523
  */
34535
- hide() {
34536
- super.hide();
34537
- this.saveSettingsDebounced.cancel();
34538
- this._isOpen = false;
34539
- this.component.unload();
34540
- invokeAsyncSafely(() => this.hideAsync());
34524
+ setDisabled(disabled) {
34525
+ super.setDisabled(disabled);
34526
+ this.textAreaComponent.setDisabled(disabled);
34527
+ return this;
34541
34528
  }
34542
34529
  /**
34543
- * Async actions to perform when the settings tab is being hidden.
34530
+ * Sets the language for code highlighting.
34544
34531
  *
34545
- * @returns A {@link Promise} that resolves when the settings tab is hidden.
34546
- */
34547
- async hideAsync() {
34548
- await this.pluginSettingsComponent.saveToFile(SAVE_TO_FILE_CONTEXT);
34549
- }
34550
- /**
34551
- * Shows the plugin settings tab.
34532
+ * @param language - The language to set.
34533
+ * @returns The component.
34552
34534
  */
34553
- show() {
34554
- this.app.setting.openTab(this);
34535
+ setLanguage(language) {
34536
+ const LANGUAGE_CLASS_PREFIX = "language-";
34537
+ for (const el of [this.preEl, this.codeEl]) {
34538
+ for (const cls of Array.from(el.classList)) {
34539
+ if (cls.startsWith(LANGUAGE_CLASS_PREFIX)) {
34540
+ el.classList.remove(cls);
34541
+ }
34542
+ }
34543
+ el.classList.add(`${LANGUAGE_CLASS_PREFIX}${language}`);
34544
+ }
34545
+ return this;
34555
34546
  }
34556
34547
  /**
34557
- * Called when the plugin settings are loaded.
34548
+ * Sets the placeholder of the component.
34558
34549
  *
34559
- * @param _loadedState - The loaded settings state.
34560
- * @param _isInitialLoad - Whether the settings are being loaded for the first time.
34561
- * @returns A {@link Promise} that resolves when the settings are loaded.
34550
+ * @param placeholder - The placeholder to set.
34551
+ * @returns The component.
34562
34552
  */
34563
- async onLoadSettings(_loadedState, _isInitialLoad) {
34564
- this.displayLegacy();
34565
- await noopAsync();
34553
+ setPlaceholder(placeholder) {
34554
+ this.placeholder = placeholder;
34555
+ invokeAsyncSafely(this.updateHighlightedCode.bind(this));
34556
+ return this;
34566
34557
  }
34567
34558
  /**
34568
- * Revalidates the settings.
34559
+ * Sets the placeholder value of the component.
34569
34560
  *
34570
- * @returns A {@link Promise} that resolves when the settings are revalidated.
34561
+ * @param placeholderValue - The placeholder value to set.
34562
+ * @returns The component.
34571
34563
  */
34572
- async revalidate() {
34573
- const validationMessages = await this.pluginSettingsComponent.revalidate();
34574
- await this.updateValidations(validationMessages);
34575
- }
34576
- getPluginSettingsProperty(propertyName) {
34577
- const settings = this.pluginSettings;
34578
- return settings[propertyName];
34579
- }
34580
- async onSaveSettings(params) {
34581
- const {
34582
- context,
34583
- newState,
34584
- oldState: _oldState
34585
- } = params;
34586
- if (context === SAVE_TO_FILE_CONTEXT) {
34587
- await this.updateValidations(newState.validationMessages);
34588
- return;
34589
- }
34590
- this.displayLegacy();
34591
- }
34592
- async updateValidations(validationMessages) {
34593
- for (const [propertyName, validationMessage] of Object.entries(validationMessages)) {
34594
- await this.triggerAsync("validationMessageChanged", propertyName, validationMessage);
34595
- }
34564
+ setPlaceholderValue(placeholderValue) {
34565
+ this.setPlaceholder(placeholderValue);
34566
+ return this;
34596
34567
  }
34597
- };
34598
-
34599
- // src/obsidian/plugin/plugin.ts
34600
- var plugin_exports = {};
34601
- __export(plugin_exports, {
34602
- PluginBase: () => PluginBase,
34603
- reloadPlugin: () => reloadPlugin,
34604
- showErrorAndDisablePlugin: () => showErrorAndDisablePlugin
34605
- });
34606
- var import_obsidian133 = require("obsidian");
34607
- init_async_events();
34608
- init_error();
34609
- init_function();
34610
- init_type_guards();
34611
- var PluginBase = class extends mixinAsyncEvents()(import_obsidian133.Plugin) {
34612
34568
  /**
34613
- * Gets abort signal component.
34569
+ * Sets the tab size of the component.
34614
34570
  *
34615
- * @returns abort signal component.
34571
+ * @param tabSize - The tab size to set.
34572
+ * @returns The component.
34616
34573
  */
34617
- get abortSignalComponent() {
34618
- return ensureNonNullable(this._abortSignalComponent);
34574
+ setTabSize(tabSize) {
34575
+ this.tabSize = tabSize;
34576
+ return this;
34619
34577
  }
34620
34578
  /**
34621
- * Sets abort signal component.
34579
+ * Sets the value of the component.
34622
34580
  *
34623
- * @param value - Abort signal component.
34581
+ * @param value - The value to set.
34582
+ * @returns The component.
34624
34583
  */
34625
- set abortSignalComponent(value) {
34626
- this._abortSignalComponent = value;
34584
+ setValue(value) {
34585
+ this.textAreaComponent.setValue(value);
34586
+ invokeAsyncSafely(this.updateHighlightedCode.bind(this));
34587
+ return this;
34627
34588
  }
34628
34589
  /**
34629
- * Gets async error handler component.
34590
+ * Simulate a change event.
34630
34591
  *
34631
- * @returns async error handler component.
34592
+ * @deprecated Use only from tests to simulate a change event.
34632
34593
  */
34633
- get asyncErrorHandlerComponent() {
34634
- return ensureNonNullable(this._asyncErrorHandlerComponent);
34594
+ simulateChange__() {
34595
+ this.simulateChangeCallback?.();
34635
34596
  }
34636
34597
  /**
34637
- * Sets async error handler component.
34638
- *
34639
- * @param value - Async error handler component.
34598
+ * Re-renders the highlighted code overlay from the current text area value. Subclasses can override to customize the render.
34640
34599
  */
34641
- set asyncErrorHandlerComponent(value) {
34642
- this._asyncErrorHandlerComponent = value;
34600
+ async updateHighlightedCode() {
34601
+ this.codeEl.textContent = this.inputEl.value || this.placeholder;
34602
+ const prism = await loadPrism();
34603
+ prism.highlightElement(this.codeEl);
34604
+ this.preEl.toggleClass("is-placeholder" /* IsPlaceholder */, this.isEmpty());
34605
+ window.requestAnimationFrame(() => {
34606
+ const gap = Math.max(0, this.inputEl.scrollHeight - this.preEl.scrollHeight);
34607
+ this.preEl.setCssProps({
34608
+ "--bottom-gap": toPx(gap)
34609
+ });
34610
+ this.handleScroll();
34611
+ });
34612
+ }
34613
+ handleKeyDown(evt) {
34614
+ if (evt.key !== "Tab") {
34615
+ return;
34616
+ }
34617
+ evt.preventDefault();
34618
+ if (evt.ctrlKey || evt.metaKey) {
34619
+ const focusables = Array.from(activeDocument.querySelectorAll(
34620
+ ':is(a, button, input, select, textarea, [tabindex]):not([tabindex="-1"]):not(:disabled):not([type="hidden"])'
34621
+ ));
34622
+ const index2 = focusables.indexOf(this.inputEl);
34623
+ const deltaIndex = evt.shiftKey ? -1 : 1;
34624
+ const nextControl = focusables[(index2 + deltaIndex + focusables.length) % focusables.length];
34625
+ nextControl?.focus();
34626
+ return;
34627
+ }
34628
+ const oldValue = this.getValue();
34629
+ const selectionStart = this.inputEl.selectionStart;
34630
+ const selectionEnd = this.inputEl.selectionEnd;
34631
+ const beforeSelection = oldValue.slice(0, selectionStart);
34632
+ const afterSelection = oldValue.slice(selectionEnd);
34633
+ const tabs = " ".repeat(this.tabSize);
34634
+ let newBeforeSelection = beforeSelection;
34635
+ if (evt.shiftKey) {
34636
+ if (beforeSelection.endsWith(tabs)) {
34637
+ newBeforeSelection = beforeSelection.slice(0, -this.tabSize);
34638
+ }
34639
+ } else {
34640
+ newBeforeSelection = beforeSelection + tabs;
34641
+ }
34642
+ const newValue = `${newBeforeSelection}${afterSelection}`;
34643
+ this.setValue(newValue);
34644
+ this.inputEl.selectionStart = newBeforeSelection.length;
34645
+ this.inputEl.selectionEnd = newBeforeSelection.length;
34646
+ }
34647
+ handleScroll() {
34648
+ this.preEl.scrollTop = this.inputEl.scrollTop;
34649
+ this.preEl.scrollLeft = this.inputEl.scrollLeft;
34643
34650
  }
34651
+ };
34652
+
34653
+ // src/obsidian/setting-components/date-component.ts
34654
+ var date_component_exports = {};
34655
+ __export(date_component_exports, {
34656
+ DateComponent: () => DateComponent
34657
+ });
34658
+ var import_obsidian134 = require("obsidian");
34659
+ init_css_class();
34660
+
34661
+ // src/obsidian/setting-components/typed-range-text-component.ts
34662
+ var typed_range_text_component_exports = {};
34663
+ __export(typed_range_text_component_exports, {
34664
+ TypedRangeTextComponent: () => TypedRangeTextComponent
34665
+ });
34666
+
34667
+ // src/obsidian/setting-components/typed-text-component.ts
34668
+ var typed_text_component_exports = {};
34669
+ __export(typed_text_component_exports, {
34670
+ TypedTextComponent: () => TypedTextComponent
34671
+ });
34672
+ var import_obsidian133 = require("obsidian");
34673
+ init_css_class();
34674
+ init_plugin_context();
34675
+ var TypedTextComponent = class extends import_obsidian133.ValueComponent {
34644
34676
  /**
34645
- * Gets the shared command handler component. Register a plugin's commands on it via
34646
- * {@link CommandHandlerComponent.registerCommandHandlers} rather than constructing your own
34647
- * {@link CommandHandlerComponent} — the app-backed active-file provider, command registrar, menu
34648
- * event registrar, and plugin name are already wired.
34677
+ * An input element of the component.
34678
+ */
34679
+ inputEl;
34680
+ /**
34681
+ * A validator element of the component.
34649
34682
  *
34650
- * @returns The command handler component.
34683
+ * @returns The validator element.
34651
34684
  */
34652
- get commandHandlerComponent() {
34653
- return ensureNonNullable(this._commandHandlerComponent);
34685
+ get validatorEl() {
34686
+ return this.inputEl;
34654
34687
  }
34655
34688
  /**
34656
- * Sets the command handler component.
34689
+ * The inner text component.
34690
+ */
34691
+ textComponent;
34692
+ /**
34693
+ * Creates a new typed text component.
34657
34694
  *
34658
- * @param value - The command handler component.
34695
+ * @param params - The parameters for the typed text component.
34659
34696
  */
34660
- set commandHandlerComponent(value) {
34661
- this._commandHandlerComponent = value;
34697
+ constructor(params) {
34698
+ super();
34699
+ this.textComponent = new import_obsidian133.TextComponent(params.containerEl);
34700
+ this.inputEl = this.textComponent.inputEl;
34701
+ this.inputEl.type = params.type;
34702
+ addPluginCssClasses(params.containerEl, params.cssClass);
34662
34703
  }
34663
34704
  /**
34664
- * Gets console debug component.
34705
+ * Gets the value of the component.
34665
34706
  *
34666
- * @returns console debug component.
34707
+ * @returns The value of the component.
34667
34708
  */
34668
- get consoleDebugComponent() {
34669
- return ensureNonNullable(this._consoleDebugComponent);
34709
+ getValue() {
34710
+ return this.valueFromString(this.textComponent.getValue());
34670
34711
  }
34671
34712
  /**
34672
- * Sets console debug component.
34713
+ * Sets the callback function to be called when the component is changed.
34673
34714
  *
34674
- * @param value - Console debug component.
34715
+ * @param callback - The callback function to be called when the component is changed.
34716
+ * @returns The component.
34675
34717
  */
34676
- set consoleDebugComponent(value) {
34677
- this._consoleDebugComponent = value;
34718
+ onChange(callback) {
34719
+ this.textComponent.onChange(() => {
34720
+ callback(this.getValue());
34721
+ });
34722
+ return this;
34678
34723
  }
34679
34724
  /**
34680
- * Gets plugin context component (plugin ID, debug controller, library styles).
34681
- *
34682
- * @returns plugin context component.
34725
+ * Called when the component is changed.
34683
34726
  */
34684
- get pluginContextComponent() {
34685
- return ensureNonNullable(this._pluginContextComponent);
34727
+ onChanged() {
34728
+ this.textComponent.onChanged();
34686
34729
  }
34687
34730
  /**
34688
- * Sets plugin context component.
34731
+ * Sets the disabled state of the component.
34689
34732
  *
34690
- * @param value - Plugin context component.
34733
+ * @param disabled - Whether the component is disabled.
34734
+ * @returns The component.
34691
34735
  */
34692
- set pluginContextComponent(value) {
34693
- this._pluginContextComponent = value;
34736
+ setDisabled(disabled) {
34737
+ super.setDisabled(disabled);
34738
+ this.textComponent.setDisabled(disabled);
34739
+ return this;
34694
34740
  }
34695
34741
  /**
34696
- * Gets plugin notice component.
34742
+ * Sets the value of the component.
34697
34743
  *
34698
- * @returns plugin notice component.
34744
+ * @param value - The value to set.
34745
+ * @returns The component.
34699
34746
  */
34700
- get pluginNoticeComponent() {
34701
- return ensureNonNullable(this._pluginNoticeComponent);
34747
+ setValue(value) {
34748
+ this.textComponent.setValue(this.valueToString(value));
34749
+ return this;
34702
34750
  }
34703
34751
  /**
34704
- * Sets plugin notice component.
34752
+ * Converts a value to a string.
34705
34753
  *
34706
- * @param value - Plugin notice component.
34754
+ * @param value - The value to convert.
34755
+ * @returns The string.
34707
34756
  */
34708
- set pluginNoticeComponent(value) {
34709
- this._pluginNoticeComponent = value;
34757
+ valueToString(value) {
34758
+ return String(value);
34710
34759
  }
34760
+ };
34761
+
34762
+ // src/obsidian/setting-components/typed-range-text-component.ts
34763
+ var TypedRangeTextComponent = class extends TypedTextComponent {
34711
34764
  /**
34712
- * Gets the editor lock component, used to lock notes read-only during long operations. Owned by
34713
- * the plugin, so its locks are released automatically when the plugin unloads.
34765
+ * Sets the maximum value of the component.
34714
34766
  *
34715
- * @returns Editor lock component.
34767
+ * @param max - The maximum value.
34768
+ * @returns The component.
34716
34769
  */
34717
- get resourceLockComponent() {
34718
- return ensureNonNullable(this._resourceLockComponent);
34770
+ setMax(max) {
34771
+ this.inputEl.max = this.valueToString(max);
34772
+ return this;
34719
34773
  }
34720
34774
  /**
34721
- * Sets the editor lock component.
34775
+ * Sets the minimum value of the component.
34722
34776
  *
34723
- * @param value - Editor lock component.
34777
+ * @param min - The minimum value.
34778
+ * @returns The component.
34724
34779
  */
34725
- set resourceLockComponent(value) {
34726
- this._resourceLockComponent = value;
34780
+ setMin(min) {
34781
+ this.inputEl.min = this.valueToString(min);
34782
+ return this;
34727
34783
  }
34728
- _abortSignalComponent;
34729
- _asyncErrorHandlerComponent;
34730
- _commandHandlerComponent;
34731
- _consoleDebugComponent;
34732
- _pluginContextComponent;
34733
- _pluginNoticeComponent;
34734
- _resourceLockComponent;
34735
- wrapperComponent = new ComponentEx();
34736
34784
  /**
34737
- * Adds a child component.
34738
- *
34739
- * The child is added to an internal wrapper component so that, during {@link onloadImpl},
34740
- * children are queued and then loaded sequentially (children-first) when the plugin loads.
34785
+ * Sets the step value of the component.
34741
34786
  *
34742
- * @typeParam TComponent - The type of component to add.
34743
- * @param component - The component instance to add.
34744
- * @returns The added component.
34787
+ * @param step - The step value.
34788
+ * @returns The component.
34745
34789
  */
34746
- addChild(component) {
34747
- return this.wrapperComponent.addChild(component);
34790
+ setStep(step) {
34791
+ this.inputEl.step = String(step);
34792
+ return this;
34748
34793
  }
34794
+ };
34795
+
34796
+ // src/obsidian/setting-components/date-component.ts
34797
+ var moment2 = extractDefaultExportInterop(import_obsidian134.moment);
34798
+ var DATE_FORMAT = "YYYY-MM-DD";
34799
+ var DateComponent = class extends TypedRangeTextComponent {
34749
34800
  /**
34750
- * Called when the external settings change.
34801
+ * Creates a new date component.
34751
34802
  *
34752
- * Override in subclass if needed. Make sure to call `await super.onExternalSettingsChange()` first.
34803
+ * @param containerEl - The container element of the component.
34753
34804
  */
34754
- async onExternalSettingsChange() {
34755
- await super.onExternalSettingsChange?.();
34756
- await this.triggerAsync("externalSettingsChange");
34805
+ constructor(containerEl) {
34806
+ super({
34807
+ containerEl,
34808
+ cssClass: "date-component" /* DateComponent */,
34809
+ type: "date"
34810
+ });
34757
34811
  }
34758
34812
  /**
34759
- * Called when the plugin is loaded.
34813
+ * Converts a string to a date.
34760
34814
  *
34761
- * Orchestrates loading: registers the universal components, lets the subclass wire its own
34762
- * components via {@link onloadImpl}, then loads all of them sequentially (children-first).
34815
+ * @param str - The string to convert.
34816
+ * @returns The date.
34817
+ */
34818
+ valueFromString(str) {
34819
+ return moment2(str, DATE_FORMAT).toDate();
34820
+ }
34821
+ /**
34822
+ * Converts a date to a string.
34763
34823
  *
34764
- * Do NOT override this method. Override {@link onloadImpl} instead.
34824
+ * @param value - The date to convert.
34825
+ * @returns The string.
34765
34826
  */
34766
- async onload() {
34767
- try {
34768
- await initI18N(this.createTranslationsMap());
34769
- this.pluginContextComponent = this.addChild(
34770
- new PluginContextComponent({
34771
- app: this.app,
34772
- pluginId: this.manifest.id
34773
- })
34774
- );
34775
- this.pluginNoticeComponent = this.addChild(
34776
- new PluginNoticeComponent({
34777
- app: this.app,
34778
- pluginName: this.manifest.name
34779
- })
34780
- );
34781
- this.asyncErrorHandlerComponent = this.addChild(new AsyncErrorHandlerComponent(this.pluginNoticeComponent));
34782
- this.abortSignalComponent = this.addChild(new AbortSignalComponent(this.manifest.id));
34783
- this.consoleDebugComponent = this.addChild(new ConsoleDebugComponent(this.manifest.id));
34784
- this.resourceLockComponent = this.addChild(new ResourceLockComponent(this.app, this.manifest.id));
34785
- this.commandHandlerComponent = this.addChild(
34786
- new CommandHandlerComponent({
34787
- activeFileProvider: new AppActiveFileProvider(this.app),
34788
- commandRegistrar: new PluginCommandRegistrar(this),
34789
- menuEventRegistrar: this.addChild(new MenuEventRegistrarComponent(this.app)),
34790
- pluginName: this.manifest.name
34791
- })
34792
- );
34793
- this.commandHandlerComponent.registerCommandHandlers([
34794
- new UnlockActiveNoteCommandHandler({
34795
- app: this.app,
34796
- resourceLockComponent: this.resourceLockComponent
34797
- })
34798
- ]);
34799
- await this.onloadImpl();
34800
- super.addChild(this.wrapperComponent);
34801
- await this.wrapperComponent.loadWithPromises();
34802
- } catch (error) {
34803
- printError(new Error(`Error loading plugin ${this.manifest.name} (${this.manifest.id})`, { cause: error }));
34804
- throw error;
34805
- }
34827
+ valueToString(value) {
34828
+ return moment2(value).format(DATE_FORMAT);
34806
34829
  }
34830
+ };
34831
+
34832
+ // src/obsidian/setting-components/date-time-component.ts
34833
+ var date_time_component_exports = {};
34834
+ __export(date_time_component_exports, {
34835
+ DateTimeComponent: () => DateTimeComponent
34836
+ });
34837
+ var import_obsidian135 = require("obsidian");
34838
+ init_css_class();
34839
+ var moment3 = extractDefaultExportInterop(import_obsidian135.moment);
34840
+ var DATE_TIME_FORMAT = "YYYY-MM-DDTHH:mm";
34841
+ var DateTimeComponent = class extends TypedRangeTextComponent {
34807
34842
  /**
34808
- * Removes a child component.
34843
+ * Creates a new date and time component.
34809
34844
  *
34810
- * @typeParam TComponent - The type of component to remove.
34811
- * @param component - The component instance to remove.
34812
- * @returns The removed component.
34845
+ * @param containerEl - The container element of the component.
34813
34846
  */
34814
- removeChild(component) {
34815
- return this.wrapperComponent.removeChild(component);
34847
+ constructor(containerEl) {
34848
+ super({
34849
+ containerEl,
34850
+ cssClass: "datetime-component" /* DateTimeComponent */,
34851
+ type: "datetime-local"
34852
+ });
34816
34853
  }
34817
34854
  /**
34818
- * Provides the translations map used to initialize i18n during {@link onload}.
34819
- *
34820
- * Override in subclass to supply plugin-specific translations. The default returns the built-in
34821
- * `obsidian-dev-utils` translations.
34855
+ * Converts a string to a date.
34822
34856
  *
34823
- * @returns The translations map.
34857
+ * @param str - The string to convert.
34858
+ * @returns The date.
34824
34859
  */
34825
- createTranslationsMap() {
34826
- return defaultTranslationsMap;
34860
+ valueFromString(str) {
34861
+ return moment3(str, DATE_TIME_FORMAT).toDate();
34827
34862
  }
34828
34863
  /**
34829
- * Called during {@link onload} to wire plugin-specific child components.
34830
- *
34831
- * Override in subclass to add child components via {@link addChild}. The universal components are
34832
- * available here. Children are loaded sequentially in the order they are added (children-first).
34864
+ * Converts a date to a string.
34833
34865
  *
34834
- * @returns A {@link Promise} that resolves when the subclass load logic is complete.
34866
+ * @param value - The date to convert.
34867
+ * @returns The string.
34835
34868
  */
34836
- onloadImpl() {
34837
- return noopAsync();
34869
+ valueToString(value) {
34870
+ return moment3(value).format(DATE_TIME_FORMAT);
34838
34871
  }
34839
34872
  };
34840
- async function reloadPlugin(plugin) {
34841
- const plugins = plugin.app.plugins;
34842
- const pluginId = plugin.manifest.id;
34843
- await plugins.disablePlugin(pluginId);
34844
- await plugins.enablePlugin(pluginId);
34845
- }
34846
- async function showErrorAndDisablePlugin(plugin, message) {
34847
- const pluginNoticeComponent = new PluginNoticeComponent({
34848
- app: plugin.app,
34849
- pluginName: plugin.manifest.name
34850
- });
34851
- pluginNoticeComponent.showNotice(message);
34852
- printError(new Error(message));
34853
- await plugin.app.plugins.disablePlugin(plugin.manifest.id);
34854
- }
34855
34873
 
34856
- // src/obsidian/plugin-cli-handler-registrar.ts
34857
- var plugin_cli_handler_registrar_exports = {};
34858
- __export(plugin_cli_handler_registrar_exports, {
34859
- PluginCliHandlerRegistrar: () => PluginCliHandlerRegistrar
34874
+ // src/obsidian/setting-components/email-component.ts
34875
+ var email_component_exports = {};
34876
+ __export(email_component_exports, {
34877
+ EmailComponent: () => EmailComponent
34860
34878
  });
34861
- var import_obsidian134 = require("obsidian");
34862
- var PluginCliHandlerRegistrar = class {
34879
+ init_css_class();
34880
+ var EmailComponent = class extends TypedTextComponent {
34863
34881
  /**
34864
- * Creates a new instance of the {@link PluginCliHandlerRegistrar} class.
34882
+ * Creates a new email component.
34865
34883
  *
34866
- * @param plugin - The Obsidian plugin instance.
34884
+ * @param containerEl - The container element of the component.
34867
34885
  */
34868
- constructor(plugin) {
34869
- this.plugin = plugin;
34886
+ constructor(containerEl) {
34887
+ super({
34888
+ containerEl,
34889
+ cssClass: "email-component" /* EmailComponent */,
34890
+ type: "email"
34891
+ });
34870
34892
  }
34871
- plugin;
34872
34893
  /**
34873
- * Registers a CLI handler.
34894
+ * Empties the component.
34895
+ */
34896
+ empty() {
34897
+ this.setValue("");
34898
+ }
34899
+ /**
34900
+ * Checks if the component is empty.
34874
34901
  *
34875
- * @param params - The parameters for the CLI handler registration.
34902
+ * @returns `true` if the component is empty, `false` otherwise.
34876
34903
  */
34877
- registerCliHandler(params) {
34878
- this.plugin.registerCliHandler(params.command, params.description, params.flags, (cliData) => normalizePromisable(params.handler(cliData)));
34904
+ isEmpty() {
34905
+ return this.getValue() === "";
34906
+ }
34907
+ /**
34908
+ * Sets the placeholder value of the component.
34909
+ *
34910
+ * @param placeholderValue - The placeholder value to set.
34911
+ * @returns The component.
34912
+ */
34913
+ setPlaceholderValue(placeholderValue) {
34914
+ this.textComponent.setPlaceholder(placeholderValue);
34915
+ return this;
34916
+ }
34917
+ /**
34918
+ * Converts a string to an email address.
34919
+ *
34920
+ * @param str - The string to convert.
34921
+ * @returns The email address.
34922
+ */
34923
+ valueFromString(str) {
34924
+ return str;
34879
34925
  }
34880
34926
  };
34881
34927
 
34882
- // src/obsidian/popovers/index.ts
34883
- var popovers_exports = {};
34884
- __export(popovers_exports, {
34885
- "field-popover": () => field_popover_exports,
34886
- popover: () => popover_exports,
34887
- "popover-anchor": () => popover_anchor_exports
34928
+ // src/obsidian/setting-components/file-component.ts
34929
+ var file_component_exports = {};
34930
+ __export(file_component_exports, {
34931
+ FileComponent: () => FileComponent
34888
34932
  });
34933
+ init_css_class();
34934
+ var FileComponent = class extends TypedTextComponent {
34935
+ /**
34936
+ * Creates a new file component.
34937
+ *
34938
+ * @param containerEl - The container element of the component.
34939
+ */
34940
+ constructor(containerEl) {
34941
+ super({
34942
+ containerEl,
34943
+ cssClass: "file-component" /* FileComponent */,
34944
+ type: "file"
34945
+ });
34946
+ }
34947
+ /**
34948
+ * Gets the value of the component.
34949
+ *
34950
+ * @returns The value of the component.
34951
+ */
34952
+ getValue() {
34953
+ return this.inputEl.files?.[0] ?? null;
34954
+ }
34955
+ /**
34956
+ * Converts a string to a file.
34957
+ *
34958
+ * @returns The file.
34959
+ */
34960
+ valueFromString() {
34961
+ return this.getValue();
34962
+ }
34963
+ /**
34964
+ * Converts a file to a string.
34965
+ *
34966
+ * @param value - The file to convert.
34967
+ * @returns The string.
34968
+ */
34969
+ valueToString(value) {
34970
+ return value?.name ?? "";
34971
+ }
34972
+ };
34889
34973
 
34890
- // src/obsidian/popovers/field-popover.ts
34891
- var field_popover_exports = {};
34892
- __export(field_popover_exports, {
34893
- editFieldsInPopover: () => editFieldsInPopover
34974
+ // src/obsidian/setting-components/month-component.ts
34975
+ var month_component_exports = {};
34976
+ __export(month_component_exports, {
34977
+ MonthComponent: () => MonthComponent
34894
34978
  });
34895
34979
  var import_obsidian136 = require("obsidian");
34896
34980
  init_css_class();
34981
+ var moment4 = extractDefaultExportInterop(import_obsidian136.moment);
34982
+ var DATE_FORMAT2 = "YYYY-MM";
34983
+ var MonthComponent = class extends TypedRangeTextComponent {
34984
+ /**
34985
+ * Creates a new month component.
34986
+ *
34987
+ * @param containerEl - The container element of the component.
34988
+ */
34989
+ constructor(containerEl) {
34990
+ super({
34991
+ containerEl,
34992
+ cssClass: "month-component" /* MonthComponent */,
34993
+ type: "month"
34994
+ });
34995
+ }
34996
+ /**
34997
+ * Converts a string to a month.
34998
+ *
34999
+ * @param str - The string to convert.
35000
+ * @returns The month.
35001
+ */
35002
+ valueFromString(str) {
35003
+ const parsed = moment4(str, DATE_FORMAT2);
35004
+ if (!parsed.isValid()) {
35005
+ throw new Error("Invalid month");
35006
+ }
35007
+ return {
35008
+ month: parsed.month() + 1,
35009
+ year: parsed.year()
35010
+ };
35011
+ }
35012
+ /**
35013
+ * Converts a month to a string.
35014
+ *
35015
+ * @param value - The month to convert.
35016
+ * @returns The string.
35017
+ */
35018
+ valueToString(value) {
35019
+ const date = moment4().year(value.year).month(value.month - 1);
35020
+ return date.format(DATE_FORMAT2);
35021
+ }
35022
+ };
34897
35023
 
34898
- // src/obsidian/popovers/popover.ts
34899
- var popover_exports = {};
34900
- __export(popover_exports, {
34901
- showPopover: () => showPopover
35024
+ // src/obsidian/setting-components/multiple-dropdown-component.ts
35025
+ var multiple_dropdown_component_exports = {};
35026
+ __export(multiple_dropdown_component_exports, {
35027
+ MultipleDropdownComponent: () => MultipleDropdownComponent
34902
35028
  });
34903
- var import_obsidian135 = require("obsidian");
35029
+ var import_obsidian137 = require("obsidian");
34904
35030
  init_css_class();
34905
35031
  init_plugin_context();
34906
- var ANCHOR_GAP_IN_PIXELS = 4;
34907
- var VIEWPORT_MARGIN_IN_PIXELS = 8;
34908
- async function showPopover(params) {
34909
- const {
34910
- anchor,
34911
- build,
34912
- cancelButtonText,
34913
- cssClasses,
34914
- okButtonText
34915
- } = params;
34916
- const doc = anchor.doc;
34917
- const win = getDocumentWindow(doc);
34918
- const popoverEl = doc.body.createDiv({ cls: "menu" });
34919
- addPluginCssClasses(popoverEl, ["popover" /* Popover */, ...cssClasses ?? []]);
34920
- return await new Promise((resolve2) => {
34921
- const state = { isClosed: false };
34922
- function close(result) {
34923
- if (state.isClosed) {
34924
- return;
34925
- }
34926
- state.isClosed = true;
34927
- doc.removeEventListener("pointerdown", handlePointerDown, true);
34928
- popoverEl.remove();
34929
- resolve2(result);
34930
- }
34931
- function handleCancel() {
34932
- close(null);
34933
- }
34934
- function handleOk() {
34935
- close(getValue());
34936
- }
34937
- function handlePointerDown(evt) {
34938
- if (evt.composedPath().includes(popoverEl)) {
34939
- return;
34940
- }
34941
- close(null);
34942
- }
34943
- const getValue = build({
34944
- cancel: handleCancel,
34945
- confirm: handleOk,
34946
- contentEl: popoverEl
34947
- });
34948
- popoverEl.addEventListener("keydown", (evt) => {
34949
- if (evt.key === "Enter") {
34950
- evt.preventDefault();
34951
- handleOk();
34952
- return;
34953
- }
34954
- if (evt.key === "Escape") {
34955
- evt.preventDefault();
34956
- handleCancel();
34957
- }
34958
- });
34959
- const buttonsSetting = new import_obsidian135.Setting(popoverEl);
34960
- buttonsSetting.addButton((button) => {
34961
- button.setButtonText(okButtonText ?? t2(($) => $.obsidianDevUtils.buttons.ok)).setCta().setClass("ok-button" /* OkButton */).onClick(handleOk);
34962
- });
34963
- buttonsSetting.addButton((button) => {
34964
- button.setButtonText(cancelButtonText ?? t2(($) => $.obsidianDevUtils.buttons.cancel)).setClass("cancel-button" /* CancelButton */).onClick(handleCancel);
34965
- });
34966
- doc.addEventListener("pointerdown", handlePointerDown, true);
34967
- positionAtAnchor(popoverEl, anchor, win);
34968
- focusFirstInput(popoverEl);
34969
- });
34970
- }
34971
- function focusFirstInput(popoverEl) {
34972
- const inputEl = popoverEl.querySelector("input");
34973
- if (!inputEl) {
34974
- return;
34975
- }
34976
- inputEl.focus();
34977
- inputEl.select();
34978
- }
34979
- function positionAtAnchor(popoverEl, anchor, win) {
34980
- const maxLeft = Math.max(VIEWPORT_MARGIN_IN_PIXELS, win.innerWidth - popoverEl.offsetWidth - VIEWPORT_MARGIN_IN_PIXELS);
34981
- const maxTop = Math.max(VIEWPORT_MARGIN_IN_PIXELS, win.innerHeight - popoverEl.offsetHeight - VIEWPORT_MARGIN_IN_PIXELS);
34982
- const left = Math.min(Math.max(anchor.left, VIEWPORT_MARGIN_IN_PIXELS), maxLeft);
34983
- const top = Math.min(Math.max(anchor.bottom + ANCHOR_GAP_IN_PIXELS, VIEWPORT_MARGIN_IN_PIXELS), maxTop);
34984
- popoverEl.style.left = `${String(Math.round(left + win.scrollX))}px`;
34985
- popoverEl.style.top = `${String(Math.round(top + win.scrollY))}px`;
34986
- }
34987
-
34988
- // src/obsidian/popovers/field-popover.ts
34989
- async function editFieldsInPopover(params) {
34990
- const {
34991
- anchor,
34992
- cancelButtonText,
34993
- cssClasses,
34994
- fields,
34995
- okButtonText
34996
- } = params;
34997
- return await showPopover(normalizeOptionalProperties({
34998
- anchor,
34999
- build({ contentEl }) {
35000
- const editors = fields.map((field) => ({
35001
- key: field.key,
35002
- textComponent: addField(contentEl, field)
35003
- }));
35004
- return () => {
35005
- const values = {};
35006
- for (const editor of editors) {
35007
- values[editor.key] = editor.textComponent.getValue();
35008
- }
35009
- return values;
35010
- };
35011
- },
35012
- cancelButtonText,
35013
- cssClasses,
35014
- okButtonText
35015
- }));
35016
- }
35017
- function addField(containerEl, field) {
35018
- const setting = new import_obsidian136.Setting(containerEl).setName(field.name);
35019
- const textComponent = new import_obsidian136.TextComponent(setting.controlEl);
35020
- textComponent.setValue(field.defaultValue ?? "");
35021
- textComponent.setPlaceholder(field.placeholder ?? "");
35022
- textComponent.inputEl.addClass("text-box" /* TextBox */);
35023
- return textComponent;
35024
- }
35025
-
35026
- // src/obsidian/react/index.ts
35027
- var react_exports = {};
35028
- __export(react_exports, {
35029
- "app-context": () => app_context_exports
35030
- });
35031
-
35032
- // src/obsidian/react/app-context.ts
35033
- var app_context_exports = {};
35034
- __export(app_context_exports, {
35035
- AppContext: () => AppContext,
35036
- useApp: () => useApp
35037
- });
35038
- var import_obsidian137 = require("obsidian");
35039
- var import_react = __toESM(require_react(), 1);
35040
- init_type_guards();
35041
- var AppContext = (0, import_react.createContext)(void 0);
35042
- function useApp() {
35043
- return ensureNonNullable((0, import_react.useContext)(AppContext), "AppContext not found");
35044
- }
35045
-
35046
- // src/obsidian/ribbon-icon-registrar.ts
35047
- var ribbon_icon_registrar_exports = {};
35048
- __export(ribbon_icon_registrar_exports, {
35049
- PluginRibbonIconRegistrar: () => PluginRibbonIconRegistrar
35050
- });
35051
- var import_obsidian138 = require("obsidian");
35052
- var PluginRibbonIconRegistrar = class {
35053
- /**
35054
- * Creates a new instance of the {@link PluginRibbonIconRegistrar} class.
35055
- *
35056
- * @param plugin - The Obsidian plugin instance.
35057
- */
35058
- constructor(plugin) {
35059
- this.plugin = plugin;
35060
- }
35061
- plugin;
35032
+ var MultipleDropdownComponent = class extends import_obsidian137.ValueComponent {
35062
35033
  /**
35063
- * Registers a ribbon icon.
35034
+ * A select element of the component.
35064
35035
  *
35065
- * @param params - The parameters for the ribbon icon registration.
35066
- * @returns The HTML element representing the registered ribbon icon.
35036
+ * @returns The select element.
35067
35037
  */
35068
- addRibbonIcon(params) {
35069
- return this.plugin.addRibbonIcon(params.icon, params.title, params.callback);
35038
+ get selectEl() {
35039
+ return this.dropdownComponent.selectEl;
35070
35040
  }
35071
- };
35072
-
35073
- // src/obsidian/setting-components/index.ts
35074
- var setting_components_exports = {};
35075
- __export(setting_components_exports, {
35076
- "checkbox-component": () => checkbox_component_exports,
35077
- "code-highlighter-component": () => code_highlighter_component_exports,
35078
- "date-component": () => date_component_exports,
35079
- "date-time-component": () => date_time_component_exports,
35080
- "email-component": () => email_component_exports,
35081
- "file-component": () => file_component_exports,
35082
- "month-component": () => month_component_exports,
35083
- "multiple-dropdown-component": () => multiple_dropdown_component_exports,
35084
- "multiple-email-component": () => multiple_email_component_exports,
35085
- "multiple-file-component": () => multiple_file_component_exports,
35086
- "multiple-text-component": () => multiple_text_component_exports,
35087
- "number-component": () => number_component_exports,
35088
- "password-component": () => password_component_exports,
35089
- "setting-component-wrapper": () => setting_component_wrapper_exports,
35090
- "telephone-component": () => telephone_component_exports,
35091
- "text-based-component": () => text_based_component_exports,
35092
- "time-component": () => time_component_exports,
35093
- "tri-state-checkbox-component": () => tri_state_checkbox_component_exports,
35094
- "typed-dropdown-component": () => typed_dropdown_component_exports,
35095
- "typed-multiple-dropdown-component": () => typed_multiple_dropdown_component_exports,
35096
- "typed-range-text-component": () => typed_range_text_component_exports,
35097
- "typed-text-component": () => typed_text_component_exports,
35098
- "url-component": () => url_component_exports,
35099
- "validator-component": () => validator_component_exports,
35100
- "value-component-with-change-tracking": () => value_component_with_change_tracking_exports,
35101
- "week-component": () => week_component_exports
35102
- });
35103
-
35104
- // src/obsidian/setting-components/checkbox-component.ts
35105
- var checkbox_component_exports = {};
35106
- __export(checkbox_component_exports, {
35107
- CheckboxComponent: () => CheckboxComponent
35108
- });
35109
- var import_obsidian139 = require("obsidian");
35110
- init_css_class();
35111
- init_plugin_context();
35112
- var CheckboxComponent = class extends import_obsidian139.ValueComponent {
35113
- /**
35114
- * An input element of the checkbox.
35115
- */
35116
- inputEl;
35117
35041
  /**
35118
- * A validator element of the checkbox.
35042
+ * A validator element of the component.
35119
35043
  *
35120
35044
  * @returns The validator element.
35121
35045
  */
35122
35046
  get validatorEl() {
35123
- return this.inputEl;
35047
+ return this.selectEl;
35124
35048
  }
35125
- changeCallback;
35126
35049
  /**
35127
- * Creates a new checkbox component.
35050
+ * The inner dropdown component.
35051
+ */
35052
+ dropdownComponent;
35053
+ simulateChangeCallback;
35054
+ /**
35055
+ * Creates a new multiple dropdown component.
35128
35056
  *
35129
- * @param containerEl - The container element.
35057
+ * @param containerEl - The container element of the component.
35130
35058
  */
35131
35059
  constructor(containerEl) {
35132
35060
  super();
35133
- addPluginCssClasses(containerEl, ["checkbox-component" /* CheckboxComponent */]);
35134
- this.inputEl = containerEl.createEl("input", { type: "checkbox" });
35135
- this.inputEl.addEventListener("change", this.onChanged.bind(this));
35061
+ this.dropdownComponent = new import_obsidian137.DropdownComponent(containerEl);
35062
+ this.dropdownComponent.selectEl.multiple = true;
35063
+ addPluginCssClasses(containerEl, "multiple-dropdown-component" /* MultipleDropdownComponent */);
35136
35064
  }
35137
35065
  /**
35138
- * Gets the value of the checkbox.
35066
+ * Adds an option to the dropdown.
35139
35067
  *
35140
- * @returns The value of the checkbox.
35068
+ * @param value - The value of the option.
35069
+ * @param display - The display text of the option.
35070
+ * @returns The component.
35141
35071
  */
35142
- getValue() {
35143
- return this.inputEl.checked;
35072
+ addOption(value, display) {
35073
+ this.dropdownComponent.addOption(value, display);
35074
+ return this;
35144
35075
  }
35145
35076
  /**
35146
- * Sets the callback to be called when the checkbox is changed.
35077
+ * Adds multiple options to the dropdown.
35147
35078
  *
35148
- * @param callback - The callback to be called when the checkbox is changed.
35079
+ * @param options - The options to add.
35149
35080
  * @returns The component.
35150
35081
  */
35151
- onChange(callback) {
35152
- this.changeCallback = callback;
35082
+ addOptions(options) {
35083
+ this.dropdownComponent.addOptions(options);
35153
35084
  return this;
35154
35085
  }
35155
35086
  /**
35156
- * Called when the checkbox is changed.
35087
+ * Gets the value of the component.
35088
+ *
35089
+ * @returns The value of the component.
35157
35090
  */
35158
- onChanged() {
35159
- this.changeCallback?.(this.getValue());
35091
+ getValue() {
35092
+ return Array.from(this.dropdownComponent.selectEl.selectedOptions).map((o2) => o2.value);
35160
35093
  }
35161
35094
  /**
35162
- * Sets the disabled state of the checkbox.
35095
+ * Sets the callback function to be called when the component is changed.
35163
35096
  *
35164
- * @param disabled - The disabled state of the checkbox.
35097
+ * @param callback - The callback function to be called when the component is changed.
35098
+ * @returns The component.
35099
+ */
35100
+ onChange(callback) {
35101
+ const changeHandler = () => {
35102
+ callback(this.getValue());
35103
+ };
35104
+ this.simulateChangeCallback = changeHandler;
35105
+ this.dropdownComponent.onChange(changeHandler);
35106
+ return this;
35107
+ }
35108
+ /**
35109
+ * Sets the disabled state of the component.
35110
+ *
35111
+ * @param disabled - The disabled state to set.
35165
35112
  * @returns The component.
35166
35113
  */
35167
35114
  setDisabled(disabled) {
35168
35115
  super.setDisabled(disabled);
35169
- this.inputEl.disabled = disabled;
35116
+ this.dropdownComponent.setDisabled(disabled);
35170
35117
  return this;
35171
35118
  }
35172
35119
  /**
35173
- * Sets the value of the checkbox.
35120
+ * Sets the value of the component.
35174
35121
  *
35175
- * @param value - The value to set the checkbox to.
35122
+ * @param value - The value to set.
35176
35123
  * @returns The component.
35177
35124
  */
35178
35125
  setValue(value) {
35179
- this.inputEl.checked = value;
35126
+ for (const option of Array.from(this.dropdownComponent.selectEl.options)) {
35127
+ option.selected = value.includes(option.value);
35128
+ }
35180
35129
  return this;
35181
35130
  }
35131
+ /**
35132
+ * Simulate a change event.
35133
+ *
35134
+ * @deprecated Use only from tests to simulate a change event.
35135
+ */
35136
+ simulateChange__() {
35137
+ this.simulateChangeCallback?.();
35138
+ }
35182
35139
  };
35183
35140
 
35184
- // src/obsidian/setting-components/code-highlighter-component.ts
35185
- var code_highlighter_component_exports = {};
35186
- __export(code_highlighter_component_exports, {
35187
- CodeHighlighterComponent: () => CodeHighlighterComponent
35141
+ // src/obsidian/setting-components/multiple-email-component.ts
35142
+ var multiple_email_component_exports = {};
35143
+ __export(multiple_email_component_exports, {
35144
+ MultipleEmailComponent: () => MultipleEmailComponent
35188
35145
  });
35189
- var import_obsidian140 = require("obsidian");
35146
+ init_css_class();
35147
+ var MultipleEmailComponent = class extends TypedTextComponent {
35148
+ /**
35149
+ * Creates a new multiple emails component.
35150
+ *
35151
+ * @param containerEl - The container element of the component.
35152
+ */
35153
+ constructor(containerEl) {
35154
+ super({
35155
+ containerEl,
35156
+ cssClass: "multiple-email-component" /* MultipleEmailComponent */,
35157
+ type: "email"
35158
+ });
35159
+ this.inputEl.multiple = true;
35160
+ }
35161
+ /**
35162
+ * Converts a string to an email address.
35163
+ *
35164
+ * @param str - The string to convert.
35165
+ * @returns The email address.
35166
+ */
35167
+ valueFromString(str) {
35168
+ return str.split(",").map((email) => email.trim());
35169
+ }
35170
+ /**
35171
+ * Converts an email address to a string.
35172
+ *
35173
+ * @param value - The email address to convert.
35174
+ * @returns The string.
35175
+ */
35176
+ valueToString(value) {
35177
+ return value.join(", ");
35178
+ }
35179
+ };
35180
+
35181
+ // src/obsidian/setting-components/multiple-file-component.ts
35182
+ var multiple_file_component_exports = {};
35183
+ __export(multiple_file_component_exports, {
35184
+ MultipleFileComponent: () => MultipleFileComponent
35185
+ });
35186
+ init_type_guards();
35187
+ init_css_class();
35188
+ var MultipleFileComponent = class extends TypedTextComponent {
35189
+ /**
35190
+ * Creates a new multiple file component.
35191
+ *
35192
+ * @param containerEl - The container element of the component.
35193
+ */
35194
+ constructor(containerEl) {
35195
+ super({
35196
+ containerEl,
35197
+ cssClass: "multiple-file-component" /* MultipleFileComponent */,
35198
+ type: "file"
35199
+ });
35200
+ this.inputEl.multiple = true;
35201
+ }
35202
+ /**
35203
+ * Gets the value of the component.
35204
+ *
35205
+ * @returns The value of the component.
35206
+ */
35207
+ getValue() {
35208
+ return Array.from(ensureNonNullable(this.inputEl.files));
35209
+ }
35210
+ /**
35211
+ * Converts a string to a file.
35212
+ *
35213
+ * @returns The file.
35214
+ */
35215
+ valueFromString() {
35216
+ return this.getValue();
35217
+ }
35218
+ /**
35219
+ * Converts a file to a string.
35220
+ *
35221
+ * @param value - The file to convert.
35222
+ * @returns The string.
35223
+ */
35224
+ valueToString(value) {
35225
+ return value[0]?.name ?? "";
35226
+ }
35227
+ };
35228
+
35229
+ // src/obsidian/setting-components/multiple-text-component.ts
35230
+ var multiple_text_component_exports = {};
35231
+ __export(multiple_text_component_exports, {
35232
+ MultipleTextComponent: () => MultipleTextComponent
35233
+ });
35234
+ var import_obsidian138 = require("obsidian");
35190
35235
  init_css_class();
35191
35236
  init_plugin_context();
35192
- var CodeHighlighterComponent = class extends import_obsidian140.ValueComponent {
35237
+ var MultipleTextComponent = class extends import_obsidian138.ValueComponent {
35193
35238
  /**
35194
35239
  * An input element of the component.
35195
35240
  *
@@ -35206,21 +35251,11 @@ var CodeHighlighterComponent = class extends import_obsidian140.ValueComponent {
35206
35251
  get validatorEl() {
35207
35252
  return this.inputEl;
35208
35253
  }
35209
- /**
35210
- * The `<code>` element that renders the syntax-highlighted overlay. Subclasses customizing the highlighting can target it.
35211
- */
35212
- codeEl;
35213
- /**
35214
- * The `<pre>` element that wraps the highlighted code overlay. Subclasses customizing the highlighting can target it.
35215
- */
35216
- preEl;
35217
35254
  /**
35218
35255
  * The inner text area component.
35219
35256
  */
35220
35257
  textAreaComponent;
35221
- placeholder = "";
35222
35258
  simulateChangeCallback;
35223
- tabSize;
35224
35259
  /**
35225
35260
  * Creates a new multiple text component.
35226
35261
  *
@@ -35228,31 +35263,14 @@ var CodeHighlighterComponent = class extends import_obsidian140.ValueComponent {
35228
35263
  */
35229
35264
  constructor(containerEl) {
35230
35265
  super();
35231
- addPluginCssClasses(containerEl, "code-highlighter-component" /* CodeHighlighterComponent */);
35232
- const wrapper = containerEl.createDiv();
35233
- addPluginCssClasses(wrapper, "setting-component-wrapper" /* SettingComponentWrapper */);
35234
- this.textAreaComponent = new import_obsidian140.TextAreaComponent(wrapper);
35235
- this.preEl = wrapper.createEl("pre", {
35236
- attr: {
35237
- tabIndex: "-1"
35238
- }
35239
- });
35240
- this.codeEl = this.preEl.createEl("code", {
35241
- attr: {
35242
- tabIndex: "-1"
35243
- }
35244
- });
35245
- this.inputEl.addEventListener("input", convertAsyncToSync(this.updateHighlightedCode.bind(this)));
35246
- this.inputEl.addEventListener("scroll", this.handleScroll.bind(this));
35247
- this.inputEl.addEventListener("keydown", this.handleKeyDown.bind(this));
35248
- const DEFAULT_TAB_SIZE = 2;
35249
- this.tabSize = DEFAULT_TAB_SIZE;
35266
+ this.textAreaComponent = new import_obsidian138.TextAreaComponent(containerEl);
35267
+ addPluginCssClasses(containerEl, "multiple-text-component" /* MultipleTextComponent */);
35250
35268
  }
35251
35269
  /**
35252
35270
  * Empties the component.
35253
35271
  */
35254
35272
  empty() {
35255
- this.setValue("");
35273
+ this.textAreaComponent.setValue("");
35256
35274
  }
35257
35275
  /**
35258
35276
  * Gets the value of the component.
@@ -35260,7 +35278,7 @@ var CodeHighlighterComponent = class extends import_obsidian140.ValueComponent {
35260
35278
  * @returns The value of the component.
35261
35279
  */
35262
35280
  getValue() {
35263
- return this.textAreaComponent.getValue();
35281
+ return this.textAreaComponent.getValue().split("\n");
35264
35282
  }
35265
35283
  /**
35266
35284
  * Checks if the component is empty.
@@ -35295,24 +35313,6 @@ var CodeHighlighterComponent = class extends import_obsidian140.ValueComponent {
35295
35313
  this.textAreaComponent.setDisabled(disabled);
35296
35314
  return this;
35297
35315
  }
35298
- /**
35299
- * Sets the language for code highlighting.
35300
- *
35301
- * @param language - The language to set.
35302
- * @returns The component.
35303
- */
35304
- setLanguage(language) {
35305
- const LANGUAGE_CLASS_PREFIX = "language-";
35306
- for (const el of [this.preEl, this.codeEl]) {
35307
- for (const cls of Array.from(el.classList)) {
35308
- if (cls.startsWith(LANGUAGE_CLASS_PREFIX)) {
35309
- el.classList.remove(cls);
35310
- }
35311
- }
35312
- el.classList.add(`${LANGUAGE_CLASS_PREFIX}${language}`);
35313
- }
35314
- return this;
35315
- }
35316
35316
  /**
35317
35317
  * Sets the placeholder of the component.
35318
35318
  *
@@ -35320,8 +35320,7 @@ var CodeHighlighterComponent = class extends import_obsidian140.ValueComponent {
35320
35320
  * @returns The component.
35321
35321
  */
35322
35322
  setPlaceholder(placeholder) {
35323
- this.placeholder = placeholder;
35324
- invokeAsyncSafely(this.updateHighlightedCode.bind(this));
35323
+ this.textAreaComponent.setPlaceholder(placeholder);
35325
35324
  return this;
35326
35325
  }
35327
35326
  /**
@@ -35331,17 +35330,7 @@ var CodeHighlighterComponent = class extends import_obsidian140.ValueComponent {
35331
35330
  * @returns The component.
35332
35331
  */
35333
35332
  setPlaceholderValue(placeholderValue) {
35334
- this.setPlaceholder(placeholderValue);
35335
- return this;
35336
- }
35337
- /**
35338
- * Sets the tab size of the component.
35339
- *
35340
- * @param tabSize - The tab size to set.
35341
- * @returns The component.
35342
- */
35343
- setTabSize(tabSize) {
35344
- this.tabSize = tabSize;
35333
+ this.setPlaceholder(this.valueToString(placeholderValue));
35345
35334
  return this;
35346
35335
  }
35347
35336
  /**
@@ -35351,8 +35340,7 @@ var CodeHighlighterComponent = class extends import_obsidian140.ValueComponent {
35351
35340
  * @returns The component.
35352
35341
  */
35353
35342
  setValue(value) {
35354
- this.textAreaComponent.setValue(value);
35355
- invokeAsyncSafely(this.updateHighlightedCode.bind(this));
35343
+ this.textAreaComponent.setValue(this.valueToString(value));
35356
35344
  return this;
35357
35345
  }
35358
35346
  /**
@@ -35364,441 +35352,312 @@ var CodeHighlighterComponent = class extends import_obsidian140.ValueComponent {
35364
35352
  this.simulateChangeCallback?.();
35365
35353
  }
35366
35354
  /**
35367
- * Re-renders the highlighted code overlay from the current text area value. Subclasses can override to customize the render.
35355
+ * Converts the value to the string shown in the text area. Subclasses can override to customize the serialization.
35356
+ *
35357
+ * @param value - The value to convert.
35358
+ * @returns The string representation of the value.
35368
35359
  */
35369
- async updateHighlightedCode() {
35370
- this.codeEl.textContent = this.inputEl.value || this.placeholder;
35371
- const prism = await loadPrism();
35372
- prism.highlightElement(this.codeEl);
35373
- this.preEl.toggleClass("is-placeholder" /* IsPlaceholder */, this.isEmpty());
35374
- window.requestAnimationFrame(() => {
35375
- const gap = Math.max(0, this.inputEl.scrollHeight - this.preEl.scrollHeight);
35376
- this.preEl.setCssProps({
35377
- "--bottom-gap": toPx(gap)
35378
- });
35379
- this.handleScroll();
35360
+ valueToString(value) {
35361
+ return value.join("\n");
35362
+ }
35363
+ };
35364
+
35365
+ // src/obsidian/setting-components/number-component.ts
35366
+ var number_component_exports = {};
35367
+ __export(number_component_exports, {
35368
+ NumberComponent: () => NumberComponent
35369
+ });
35370
+ init_css_class();
35371
+ var NumberComponent = class extends TypedRangeTextComponent {
35372
+ /**
35373
+ * Creates a new number component.
35374
+ *
35375
+ * @param containerEl - The container element of the component.
35376
+ */
35377
+ constructor(containerEl) {
35378
+ super({
35379
+ containerEl,
35380
+ cssClass: "number-component" /* NumberComponent */,
35381
+ type: "number"
35380
35382
  });
35381
35383
  }
35382
- handleKeyDown(evt) {
35383
- if (evt.key !== "Tab") {
35384
- return;
35385
- }
35386
- evt.preventDefault();
35387
- if (evt.ctrlKey || evt.metaKey) {
35388
- const focusables = Array.from(activeDocument.querySelectorAll(
35389
- ':is(a, button, input, select, textarea, [tabindex]):not([tabindex="-1"]):not(:disabled):not([type="hidden"])'
35390
- ));
35391
- const index2 = focusables.indexOf(this.inputEl);
35392
- const deltaIndex = evt.shiftKey ? -1 : 1;
35393
- const nextControl = focusables[(index2 + deltaIndex + focusables.length) % focusables.length];
35394
- nextControl?.focus();
35395
- return;
35396
- }
35397
- const oldValue = this.getValue();
35398
- const selectionStart = this.inputEl.selectionStart;
35399
- const selectionEnd = this.inputEl.selectionEnd;
35400
- const beforeSelection = oldValue.slice(0, selectionStart);
35401
- const afterSelection = oldValue.slice(selectionEnd);
35402
- const tabs = " ".repeat(this.tabSize);
35403
- let newBeforeSelection = beforeSelection;
35404
- if (evt.shiftKey) {
35405
- if (beforeSelection.endsWith(tabs)) {
35406
- newBeforeSelection = beforeSelection.slice(0, -this.tabSize);
35407
- }
35408
- } else {
35409
- newBeforeSelection = beforeSelection + tabs;
35410
- }
35411
- const newValue = `${newBeforeSelection}${afterSelection}`;
35412
- this.setValue(newValue);
35413
- this.inputEl.selectionStart = newBeforeSelection.length;
35414
- this.inputEl.selectionEnd = newBeforeSelection.length;
35415
- }
35416
- handleScroll() {
35417
- this.preEl.scrollTop = this.inputEl.scrollTop;
35418
- this.preEl.scrollLeft = this.inputEl.scrollLeft;
35419
- }
35420
- };
35421
-
35422
- // src/obsidian/setting-components/date-component.ts
35423
- var date_component_exports = {};
35424
- __export(date_component_exports, {
35425
- DateComponent: () => DateComponent
35426
- });
35427
- var import_obsidian142 = require("obsidian");
35428
- init_css_class();
35429
-
35430
- // src/obsidian/setting-components/typed-range-text-component.ts
35431
- var typed_range_text_component_exports = {};
35432
- __export(typed_range_text_component_exports, {
35433
- TypedRangeTextComponent: () => TypedRangeTextComponent
35434
- });
35435
-
35436
- // src/obsidian/setting-components/typed-text-component.ts
35437
- var typed_text_component_exports = {};
35438
- __export(typed_text_component_exports, {
35439
- TypedTextComponent: () => TypedTextComponent
35440
- });
35441
- var import_obsidian141 = require("obsidian");
35442
- init_css_class();
35443
- init_plugin_context();
35444
- var TypedTextComponent = class extends import_obsidian141.ValueComponent {
35445
- /**
35446
- * An input element of the component.
35447
- */
35448
- inputEl;
35449
- /**
35450
- * A validator element of the component.
35451
- *
35452
- * @returns The validator element.
35453
- */
35454
- get validatorEl() {
35455
- return this.inputEl;
35456
- }
35457
- /**
35458
- * The inner text component.
35459
- */
35460
- textComponent;
35461
- /**
35462
- * Creates a new typed text component.
35463
- *
35464
- * @param params - The parameters for the typed text component.
35465
- */
35466
- constructor(params) {
35467
- super();
35468
- this.textComponent = new import_obsidian141.TextComponent(params.containerEl);
35469
- this.inputEl = this.textComponent.inputEl;
35470
- this.inputEl.type = params.type;
35471
- addPluginCssClasses(params.containerEl, params.cssClass);
35472
- }
35473
35384
  /**
35474
- * Gets the value of the component.
35475
- *
35476
- * @returns The value of the component.
35385
+ * Empties the component.
35477
35386
  */
35478
- getValue() {
35479
- return this.valueFromString(this.textComponent.getValue());
35387
+ empty() {
35388
+ this.textComponent.setValue("");
35480
35389
  }
35481
35390
  /**
35482
- * Sets the callback function to be called when the component is changed.
35391
+ * Checks if the component is empty.
35483
35392
  *
35484
- * @param callback - The callback function to be called when the component is changed.
35485
- * @returns The component.
35486
- */
35487
- onChange(callback) {
35488
- this.textComponent.onChange(() => {
35489
- callback(this.getValue());
35490
- });
35491
- return this;
35492
- }
35493
- /**
35494
- * Called when the component is changed.
35393
+ * @returns `true` if the component is empty, `false` otherwise.
35495
35394
  */
35496
- onChanged() {
35497
- this.textComponent.onChanged();
35395
+ isEmpty() {
35396
+ return this.textComponent.getValue() === "";
35498
35397
  }
35499
35398
  /**
35500
- * Sets the disabled state of the component.
35399
+ * Sets the placeholder of the component.
35501
35400
  *
35502
- * @param disabled - Whether the component is disabled.
35401
+ * @param placeholder - The placeholder to set.
35503
35402
  * @returns The component.
35504
35403
  */
35505
- setDisabled(disabled) {
35506
- super.setDisabled(disabled);
35507
- this.textComponent.setDisabled(disabled);
35404
+ setPlaceholder(placeholder) {
35405
+ this.textComponent.setPlaceholder(placeholder);
35508
35406
  return this;
35509
35407
  }
35510
35408
  /**
35511
- * Sets the value of the component.
35409
+ * Sets the placeholder value of the component.
35512
35410
  *
35513
- * @param value - The value to set.
35411
+ * @param placeholderValue - The placeholder value to set.
35514
35412
  * @returns The component.
35515
35413
  */
35516
- setValue(value) {
35517
- this.textComponent.setValue(this.valueToString(value));
35414
+ setPlaceholderValue(placeholderValue) {
35415
+ this.textComponent.setPlaceholder(this.valueToString(placeholderValue));
35518
35416
  return this;
35519
35417
  }
35520
35418
  /**
35521
- * Converts a value to a string.
35419
+ * Converts a string to a number.
35522
35420
  *
35523
- * @param value - The value to convert.
35524
- * @returns The string.
35421
+ * @param str - The string to convert.
35422
+ * @returns The number.
35525
35423
  */
35526
- valueToString(value) {
35527
- return String(value);
35424
+ valueFromString(str) {
35425
+ return parseInt(str, 10);
35528
35426
  }
35529
35427
  };
35530
35428
 
35531
- // src/obsidian/setting-components/typed-range-text-component.ts
35532
- var TypedRangeTextComponent = class extends TypedTextComponent {
35429
+ // src/obsidian/setting-components/password-component.ts
35430
+ var password_component_exports = {};
35431
+ __export(password_component_exports, {
35432
+ PasswordComponent: () => PasswordComponent
35433
+ });
35434
+ init_css_class();
35435
+ var PasswordComponent = class extends TypedTextComponent {
35533
35436
  /**
35534
- * Sets the maximum value of the component.
35437
+ * Creates a new password component.
35535
35438
  *
35536
- * @param max - The maximum value.
35537
- * @returns The component.
35439
+ * @param containerEl - The container element of the component.
35538
35440
  */
35539
- setMax(max) {
35540
- this.inputEl.max = this.valueToString(max);
35541
- return this;
35441
+ constructor(containerEl) {
35442
+ super({
35443
+ containerEl,
35444
+ cssClass: "password-component" /* PasswordComponent */,
35445
+ type: "password"
35446
+ });
35542
35447
  }
35543
35448
  /**
35544
- * Sets the minimum value of the component.
35449
+ * Sets the placeholder value of the component.
35545
35450
  *
35546
- * @param min - The minimum value.
35451
+ * @param placeholder - The placeholder to set.
35547
35452
  * @returns The component.
35548
35453
  */
35549
- setMin(min) {
35550
- this.inputEl.min = this.valueToString(min);
35454
+ setPlaceholder(placeholder) {
35455
+ this.textComponent.setPlaceholder(placeholder);
35551
35456
  return this;
35552
35457
  }
35553
35458
  /**
35554
- * Sets the step value of the component.
35459
+ * Gets the value from a string.
35555
35460
  *
35556
- * @param step - The step value.
35557
- * @returns The component.
35461
+ * @param str - The string to get the value from.
35462
+ * @returns The value from the string.
35558
35463
  */
35559
- setStep(step) {
35560
- this.inputEl.step = String(step);
35561
- return this;
35464
+ valueFromString(str) {
35465
+ return str;
35562
35466
  }
35563
35467
  };
35564
35468
 
35565
- // src/obsidian/setting-components/date-component.ts
35566
- var moment2 = extractDefaultExportInterop(import_obsidian142.moment);
35567
- var DATE_FORMAT = "YYYY-MM-DD";
35568
- var DateComponent = class extends TypedRangeTextComponent {
35469
+ // src/obsidian/setting-components/telephone-component.ts
35470
+ var telephone_component_exports = {};
35471
+ __export(telephone_component_exports, {
35472
+ TelephoneComponent: () => TelephoneComponent
35473
+ });
35474
+ init_css_class();
35475
+ var TelephoneComponent = class extends TypedTextComponent {
35569
35476
  /**
35570
- * Creates a new date component.
35477
+ * Creates a new telephone component.
35571
35478
  *
35572
35479
  * @param containerEl - The container element of the component.
35573
35480
  */
35574
35481
  constructor(containerEl) {
35575
35482
  super({
35576
35483
  containerEl,
35577
- cssClass: "date-component" /* DateComponent */,
35578
- type: "date"
35484
+ cssClass: "telephone-component" /* TelephoneComponent */,
35485
+ type: "tel"
35579
35486
  });
35580
35487
  }
35581
35488
  /**
35582
- * Converts a string to a date.
35489
+ * Empties the component.
35490
+ */
35491
+ empty() {
35492
+ this.textComponent.setValue("");
35493
+ }
35494
+ /**
35495
+ * Checks if the component is empty.
35583
35496
  *
35584
- * @param str - The string to convert.
35585
- * @returns The date.
35497
+ * @returns `true` if the component is empty, `false` otherwise.
35586
35498
  */
35587
- valueFromString(str) {
35588
- return moment2(str, DATE_FORMAT).toDate();
35499
+ isEmpty() {
35500
+ return this.textComponent.getValue() === "";
35589
35501
  }
35590
35502
  /**
35591
- * Converts a date to a string.
35503
+ * Sets the placeholder value of the component.
35592
35504
  *
35593
- * @param value - The date to convert.
35594
- * @returns The string.
35505
+ * @param placeholderValue - The placeholder value to set.
35506
+ * @returns The component.
35595
35507
  */
35596
- valueToString(value) {
35597
- return moment2(value).format(DATE_FORMAT);
35508
+ setPlaceholderValue(placeholderValue) {
35509
+ this.textComponent.setPlaceholder(placeholderValue);
35510
+ return this;
35511
+ }
35512
+ /**
35513
+ * Gets the value from a string.
35514
+ *
35515
+ * @param str - The string to get the value from.
35516
+ * @returns The value from the string.
35517
+ */
35518
+ valueFromString(str) {
35519
+ return str;
35598
35520
  }
35599
35521
  };
35600
35522
 
35601
- // src/obsidian/setting-components/date-time-component.ts
35602
- var date_time_component_exports = {};
35603
- __export(date_time_component_exports, {
35604
- DateTimeComponent: () => DateTimeComponent
35523
+ // src/obsidian/setting-components/time-component.ts
35524
+ var time_component_exports = {};
35525
+ __export(time_component_exports, {
35526
+ TimeComponent: () => TimeComponent
35605
35527
  });
35606
- var import_obsidian143 = require("obsidian");
35528
+ var import_obsidian139 = require("obsidian");
35607
35529
  init_css_class();
35608
- var moment3 = extractDefaultExportInterop(import_obsidian143.moment);
35609
- var DATE_TIME_FORMAT = "YYYY-MM-DDTHH:mm";
35610
- var DateTimeComponent = class extends TypedRangeTextComponent {
35530
+ var TimeComponent = class extends TypedRangeTextComponent {
35611
35531
  /**
35612
- * Creates a new date and time component.
35532
+ * Creates a new time component.
35613
35533
  *
35614
35534
  * @param containerEl - The container element of the component.
35615
35535
  */
35616
35536
  constructor(containerEl) {
35617
35537
  super({
35618
35538
  containerEl,
35619
- cssClass: "datetime-component" /* DateTimeComponent */,
35620
- type: "datetime-local"
35539
+ cssClass: "time-component" /* TimeComponent */,
35540
+ type: "time"
35621
35541
  });
35622
35542
  }
35623
35543
  /**
35624
- * Converts a string to a date.
35544
+ * Converts a string to a time.
35625
35545
  *
35626
35546
  * @param str - The string to convert.
35627
35547
  * @returns The date.
35628
35548
  */
35629
35549
  valueFromString(str) {
35630
- return moment3(str, DATE_TIME_FORMAT).toDate();
35550
+ return import_obsidian139.moment.duration(str);
35631
35551
  }
35632
35552
  /**
35633
- * Converts a date to a string.
35553
+ * Converts a time to a string.
35634
35554
  *
35635
- * @param value - The date to convert.
35555
+ * @param value - The time to convert.
35636
35556
  * @returns The string.
35637
35557
  */
35638
35558
  valueToString(value) {
35639
- return moment3(value).format(DATE_TIME_FORMAT);
35640
- }
35641
- };
35559
+ let format2;
35560
+ if (value.milliseconds() > 0) {
35561
+ format2 = "HH:mm:ss.SSS";
35562
+ } else if (value.seconds() > 0) {
35563
+ format2 = "HH:mm:ss";
35564
+ } else {
35565
+ format2 = "HH:mm";
35566
+ }
35567
+ return import_obsidian139.moment.utc(value.asMilliseconds()).format(format2);
35568
+ }
35569
+ };
35642
35570
 
35643
- // src/obsidian/setting-components/email-component.ts
35644
- var email_component_exports = {};
35645
- __export(email_component_exports, {
35646
- EmailComponent: () => EmailComponent
35571
+ // src/obsidian/setting-components/tri-state-checkbox-component.ts
35572
+ var tri_state_checkbox_component_exports = {};
35573
+ __export(tri_state_checkbox_component_exports, {
35574
+ TriStateCheckboxComponent: () => TriStateCheckboxComponent
35647
35575
  });
35576
+ var import_obsidian140 = require("obsidian");
35648
35577
  init_css_class();
35649
- var EmailComponent = class extends TypedTextComponent {
35650
- /**
35651
- * Creates a new email component.
35652
- *
35653
- * @param containerEl - The container element of the component.
35654
- */
35655
- constructor(containerEl) {
35656
- super({
35657
- containerEl,
35658
- cssClass: "email-component" /* EmailComponent */,
35659
- type: "email"
35660
- });
35661
- }
35662
- /**
35663
- * Empties the component.
35664
- */
35665
- empty() {
35666
- this.setValue("");
35667
- }
35668
- /**
35669
- * Checks if the component is empty.
35670
- *
35671
- * @returns `true` if the component is empty, `false` otherwise.
35672
- */
35673
- isEmpty() {
35674
- return this.getValue() === "";
35675
- }
35578
+ init_plugin_context();
35579
+ var TriStateCheckboxComponent = class extends import_obsidian140.ValueComponent {
35676
35580
  /**
35677
- * Sets the placeholder value of the component.
35678
- *
35679
- * @param placeholderValue - The placeholder value to set.
35680
- * @returns The component.
35581
+ * An input element of the checkbox.
35681
35582
  */
35682
- setPlaceholderValue(placeholderValue) {
35683
- this.textComponent.setPlaceholder(placeholderValue);
35684
- return this;
35685
- }
35583
+ inputEl;
35686
35584
  /**
35687
- * Converts a string to an email address.
35585
+ * A validator element of the checkbox.
35688
35586
  *
35689
- * @param str - The string to convert.
35690
- * @returns The email address.
35587
+ * @returns The validator element.
35691
35588
  */
35692
- valueFromString(str) {
35693
- return str;
35589
+ get validatorEl() {
35590
+ return this.inputEl;
35694
35591
  }
35695
- };
35696
-
35697
- // src/obsidian/setting-components/file-component.ts
35698
- var file_component_exports = {};
35699
- __export(file_component_exports, {
35700
- FileComponent: () => FileComponent
35701
- });
35702
- init_css_class();
35703
- var FileComponent = class extends TypedTextComponent {
35592
+ changeCallback;
35704
35593
  /**
35705
- * Creates a new file component.
35594
+ * Creates a new tri-state checkbox component.
35706
35595
  *
35707
- * @param containerEl - The container element of the component.
35596
+ * @param containerEl - The container element.
35708
35597
  */
35709
35598
  constructor(containerEl) {
35710
- super({
35711
- containerEl,
35712
- cssClass: "file-component" /* FileComponent */,
35713
- type: "file"
35714
- });
35599
+ super();
35600
+ addPluginCssClasses(containerEl, "tri-state-checkbox-component" /* TriStateCheckboxComponent */);
35601
+ this.inputEl = containerEl.createEl("input", { type: "checkbox" });
35602
+ this.inputEl.addEventListener("change", this.onChanged.bind(this));
35715
35603
  }
35716
35604
  /**
35717
- * Gets the value of the component.
35605
+ * Gets the value of the checkbox.
35718
35606
  *
35719
- * @returns The value of the component.
35607
+ * @returns The value of the checkbox.
35720
35608
  */
35721
35609
  getValue() {
35722
- return this.inputEl.files?.[0] ?? null;
35723
- }
35724
- /**
35725
- * Converts a string to a file.
35726
- *
35727
- * @returns The file.
35728
- */
35729
- valueFromString() {
35730
- return this.getValue();
35610
+ return this.inputEl.indeterminate ? null : this.inputEl.checked;
35731
35611
  }
35732
35612
  /**
35733
- * Converts a file to a string.
35613
+ * Sets the callback to be called when the checkbox is changed.
35734
35614
  *
35735
- * @param value - The file to convert.
35736
- * @returns The string.
35615
+ * @param callback - The callback to be called when the checkbox is changed.
35616
+ * @returns The component.
35737
35617
  */
35738
- valueToString(value) {
35739
- return value?.name ?? "";
35618
+ onChange(callback) {
35619
+ this.changeCallback = callback;
35620
+ return this;
35740
35621
  }
35741
- };
35742
-
35743
- // src/obsidian/setting-components/month-component.ts
35744
- var month_component_exports = {};
35745
- __export(month_component_exports, {
35746
- MonthComponent: () => MonthComponent
35747
- });
35748
- var import_obsidian144 = require("obsidian");
35749
- init_css_class();
35750
- var moment4 = extractDefaultExportInterop(import_obsidian144.moment);
35751
- var DATE_FORMAT2 = "YYYY-MM";
35752
- var MonthComponent = class extends TypedRangeTextComponent {
35753
35622
  /**
35754
- * Creates a new month component.
35755
- *
35756
- * @param containerEl - The container element of the component.
35623
+ * Called when the checkbox is changed.
35757
35624
  */
35758
- constructor(containerEl) {
35759
- super({
35760
- containerEl,
35761
- cssClass: "month-component" /* MonthComponent */,
35762
- type: "month"
35763
- });
35625
+ onChanged() {
35626
+ this.changeCallback?.(this.getValue());
35764
35627
  }
35765
35628
  /**
35766
- * Converts a string to a month.
35629
+ * Sets the disabled state of the checkbox.
35767
35630
  *
35768
- * @param str - The string to convert.
35769
- * @returns The month.
35631
+ * @param disabled - The disabled state of the checkbox.
35632
+ * @returns The component.
35770
35633
  */
35771
- valueFromString(str) {
35772
- const parsed = moment4(str, DATE_FORMAT2);
35773
- if (!parsed.isValid()) {
35774
- throw new Error("Invalid month");
35775
- }
35776
- return {
35777
- month: parsed.month() + 1,
35778
- year: parsed.year()
35779
- };
35634
+ setDisabled(disabled) {
35635
+ super.setDisabled(disabled);
35636
+ this.inputEl.disabled = disabled;
35637
+ return this;
35780
35638
  }
35781
35639
  /**
35782
- * Converts a month to a string.
35640
+ * Sets the value of the checkbox.
35783
35641
  *
35784
- * @param value - The month to convert.
35785
- * @returns The string.
35642
+ * @param value - The value to set the checkbox to.
35643
+ * @returns The component.
35786
35644
  */
35787
- valueToString(value) {
35788
- const date = moment4().year(value.year).month(value.month - 1);
35789
- return date.format(DATE_FORMAT2);
35645
+ setValue(value) {
35646
+ this.inputEl.indeterminate = value === null;
35647
+ this.inputEl.checked = value ?? false;
35648
+ return this;
35790
35649
  }
35791
35650
  };
35792
35651
 
35793
- // src/obsidian/setting-components/multiple-dropdown-component.ts
35794
- var multiple_dropdown_component_exports = {};
35795
- __export(multiple_dropdown_component_exports, {
35796
- MultipleDropdownComponent: () => MultipleDropdownComponent
35652
+ // src/obsidian/setting-components/typed-dropdown-component.ts
35653
+ var typed_dropdown_component_exports = {};
35654
+ __export(typed_dropdown_component_exports, {
35655
+ TypedDropdownComponent: () => TypedDropdownComponent
35797
35656
  });
35798
- var import_obsidian145 = require("obsidian");
35657
+ var import_obsidian141 = require("obsidian");
35799
35658
  init_css_class();
35800
35659
  init_plugin_context();
35801
- var MultipleDropdownComponent = class extends import_obsidian145.ValueComponent {
35660
+ var TypedDropdownComponent = class extends import_obsidian141.ValueComponent {
35802
35661
  /**
35803
35662
  * A select element of the component.
35804
35663
  *
@@ -35819,6 +35678,10 @@ var MultipleDropdownComponent = class extends import_obsidian145.ValueComponent
35819
35678
  * The inner dropdown component.
35820
35679
  */
35821
35680
  dropdownComponent;
35681
+ /**
35682
+ * The list of selectable option values, indexed by their position in the dropdown.
35683
+ */
35684
+ values = [];
35822
35685
  simulateChangeCallback;
35823
35686
  /**
35824
35687
  * Creates a new multiple dropdown component.
@@ -35827,9 +35690,8 @@ var MultipleDropdownComponent = class extends import_obsidian145.ValueComponent
35827
35690
  */
35828
35691
  constructor(containerEl) {
35829
35692
  super();
35830
- this.dropdownComponent = new import_obsidian145.DropdownComponent(containerEl);
35831
- this.dropdownComponent.selectEl.multiple = true;
35832
- addPluginCssClasses(containerEl, "multiple-dropdown-component" /* MultipleDropdownComponent */);
35693
+ this.dropdownComponent = new import_obsidian141.DropdownComponent(containerEl);
35694
+ addPluginCssClasses(containerEl, "typed-dropdown-component" /* TypedDropdownComponent */);
35833
35695
  }
35834
35696
  /**
35835
35697
  * Adds an option to the dropdown.
@@ -35839,7 +35701,12 @@ var MultipleDropdownComponent = class extends import_obsidian145.ValueComponent
35839
35701
  * @returns The component.
35840
35702
  */
35841
35703
  addOption(value, display) {
35842
- this.dropdownComponent.addOption(value, display);
35704
+ let index2 = this.values.indexOf(value);
35705
+ if (index2 === -1) {
35706
+ this.values.push(value);
35707
+ index2 = this.values.length - 1;
35708
+ }
35709
+ this.dropdownComponent.addOption(String(index2), display);
35843
35710
  return this;
35844
35711
  }
35845
35712
  /**
@@ -35849,7 +35716,9 @@ var MultipleDropdownComponent = class extends import_obsidian145.ValueComponent
35849
35716
  * @returns The component.
35850
35717
  */
35851
35718
  addOptions(options) {
35852
- this.dropdownComponent.addOptions(options);
35719
+ for (const [value, display] of options.entries()) {
35720
+ this.addOption(value, display);
35721
+ }
35853
35722
  return this;
35854
35723
  }
35855
35724
  /**
@@ -35858,7 +35727,7 @@ var MultipleDropdownComponent = class extends import_obsidian145.ValueComponent
35858
35727
  * @returns The value of the component.
35859
35728
  */
35860
35729
  getValue() {
35861
- return Array.from(this.dropdownComponent.selectEl.selectedOptions).map((o2) => o2.value);
35730
+ return this.values[this.dropdownComponent.selectEl.selectedIndex] ?? null;
35862
35731
  }
35863
35732
  /**
35864
35733
  * Sets the callback function to be called when the component is changed.
@@ -35892,9 +35761,8 @@ var MultipleDropdownComponent = class extends import_obsidian145.ValueComponent
35892
35761
  * @returns The component.
35893
35762
  */
35894
35763
  setValue(value) {
35895
- for (const option of Array.from(this.dropdownComponent.selectEl.options)) {
35896
- option.selected = value.includes(option.value);
35897
- }
35764
+ const index2 = value === null ? -1 : this.values.indexOf(value);
35765
+ this.dropdownComponent.selectEl.selectedIndex = index2;
35898
35766
  return this;
35899
35767
  }
35900
35768
  /**
@@ -35907,160 +35775,91 @@ var MultipleDropdownComponent = class extends import_obsidian145.ValueComponent
35907
35775
  }
35908
35776
  };
35909
35777
 
35910
- // src/obsidian/setting-components/multiple-email-component.ts
35911
- var multiple_email_component_exports = {};
35912
- __export(multiple_email_component_exports, {
35913
- MultipleEmailComponent: () => MultipleEmailComponent
35778
+ // src/obsidian/setting-components/typed-multiple-dropdown-component.ts
35779
+ var typed_multiple_dropdown_component_exports = {};
35780
+ __export(typed_multiple_dropdown_component_exports, {
35781
+ TypedMultipleDropdownComponent: () => TypedMultipleDropdownComponent
35914
35782
  });
35783
+ var import_obsidian142 = require("obsidian");
35915
35784
  init_css_class();
35916
- var MultipleEmailComponent = class extends TypedTextComponent {
35785
+ init_plugin_context();
35786
+ var TypedMultipleDropdownComponent = class extends import_obsidian142.ValueComponent {
35917
35787
  /**
35918
- * Creates a new multiple emails component.
35788
+ * A select element of the component.
35919
35789
  *
35920
- * @param containerEl - The container element of the component.
35790
+ * @returns The select element.
35921
35791
  */
35922
- constructor(containerEl) {
35923
- super({
35924
- containerEl,
35925
- cssClass: "multiple-email-component" /* MultipleEmailComponent */,
35926
- type: "email"
35927
- });
35928
- this.inputEl.multiple = true;
35792
+ get selectEl() {
35793
+ return this.multipleDropdownComponent.selectEl;
35929
35794
  }
35930
35795
  /**
35931
- * Converts a string to an email address.
35796
+ * A validator element of the component.
35932
35797
  *
35933
- * @param str - The string to convert.
35934
- * @returns The email address.
35798
+ * @returns The validator element.
35935
35799
  */
35936
- valueFromString(str) {
35937
- return str.split(",").map((email) => email.trim());
35800
+ get validatorEl() {
35801
+ return this.selectEl;
35938
35802
  }
35939
35803
  /**
35940
- * Converts an email address to a string.
35941
- *
35942
- * @param value - The email address to convert.
35943
- * @returns The string.
35804
+ * The inner multiple dropdown component.
35944
35805
  */
35945
- valueToString(value) {
35946
- return value.join(", ");
35947
- }
35948
- };
35949
-
35950
- // src/obsidian/setting-components/multiple-file-component.ts
35951
- var multiple_file_component_exports = {};
35952
- __export(multiple_file_component_exports, {
35953
- MultipleFileComponent: () => MultipleFileComponent
35954
- });
35955
- init_type_guards();
35956
- init_css_class();
35957
- var MultipleFileComponent = class extends TypedTextComponent {
35806
+ multipleDropdownComponent;
35958
35807
  /**
35959
- * Creates a new multiple file component.
35960
- *
35961
- * @param containerEl - The container element of the component.
35962
- */
35963
- constructor(containerEl) {
35964
- super({
35965
- containerEl,
35966
- cssClass: "multiple-file-component" /* MultipleFileComponent */,
35967
- type: "file"
35968
- });
35969
- this.inputEl.multiple = true;
35970
- }
35971
- /**
35972
- * Gets the value of the component.
35973
- *
35974
- * @returns The value of the component.
35975
- */
35976
- getValue() {
35977
- return Array.from(ensureNonNullable(this.inputEl.files));
35978
- }
35979
- /**
35980
- * Converts a string to a file.
35981
- *
35982
- * @returns The file.
35983
- */
35984
- valueFromString() {
35985
- return this.getValue();
35986
- }
35987
- /**
35988
- * Converts a file to a string.
35989
- *
35990
- * @param value - The file to convert.
35991
- * @returns The string.
35992
- */
35993
- valueToString(value) {
35994
- return value[0]?.name ?? "";
35995
- }
35996
- };
35997
-
35998
- // src/obsidian/setting-components/multiple-text-component.ts
35999
- var multiple_text_component_exports = {};
36000
- __export(multiple_text_component_exports, {
36001
- MultipleTextComponent: () => MultipleTextComponent
36002
- });
36003
- var import_obsidian146 = require("obsidian");
36004
- init_css_class();
36005
- init_plugin_context();
36006
- var MultipleTextComponent = class extends import_obsidian146.ValueComponent {
36007
- /**
36008
- * An input element of the component.
36009
- *
36010
- * @returns The input element of the component.
36011
- */
36012
- get inputEl() {
36013
- return this.textAreaComponent.inputEl;
36014
- }
36015
- /**
36016
- * Gets the validator element of the component.
36017
- *
36018
- * @returns The validator element of the component.
36019
- */
36020
- get validatorEl() {
36021
- return this.inputEl;
36022
- }
36023
- /**
36024
- * The inner text area component.
35808
+ * The list of selectable option values, indexed by their position in the dropdown.
36025
35809
  */
36026
- textAreaComponent;
35810
+ values = [];
36027
35811
  simulateChangeCallback;
36028
35812
  /**
36029
- * Creates a new multiple text component.
35813
+ * Creates a new multiple dropdown component.
36030
35814
  *
36031
35815
  * @param containerEl - The container element of the component.
36032
35816
  */
36033
35817
  constructor(containerEl) {
36034
35818
  super();
36035
- this.textAreaComponent = new import_obsidian146.TextAreaComponent(containerEl);
36036
- addPluginCssClasses(containerEl, "multiple-text-component" /* MultipleTextComponent */);
35819
+ this.multipleDropdownComponent = new MultipleDropdownComponent(containerEl);
35820
+ addPluginCssClasses(containerEl, "typed-multiple-dropdown-component" /* TypedMultipleDropdownComponent */);
36037
35821
  }
36038
35822
  /**
36039
- * Empties the component.
35823
+ * Adds an option to the dropdown.
35824
+ *
35825
+ * @param value - The value of the option.
35826
+ * @param display - The display text of the option.
35827
+ * @returns The component.
36040
35828
  */
36041
- empty() {
36042
- this.textAreaComponent.setValue("");
35829
+ addOption(value, display) {
35830
+ let index2 = this.values.indexOf(value);
35831
+ if (index2 === -1) {
35832
+ this.values.push(value);
35833
+ index2 = this.values.length - 1;
35834
+ }
35835
+ this.multipleDropdownComponent.addOption(String(index2), display);
35836
+ return this;
36043
35837
  }
36044
35838
  /**
36045
- * Gets the value of the component.
35839
+ * Adds multiple options to the dropdown.
36046
35840
  *
36047
- * @returns The value of the component.
35841
+ * @param options - The options to add.
35842
+ * @returns The component.
36048
35843
  */
36049
- getValue() {
36050
- return this.textAreaComponent.getValue().split("\n");
35844
+ addOptions(options) {
35845
+ for (const [value, display] of options.entries()) {
35846
+ this.addOption(value, display);
35847
+ }
35848
+ return this;
36051
35849
  }
36052
35850
  /**
36053
- * Checks if the component is empty.
35851
+ * Gets the value of the component.
36054
35852
  *
36055
- * @returns `true` if the component is empty, `false` otherwise.
35853
+ * @returns The value of the component.
36056
35854
  */
36057
- isEmpty() {
36058
- return this.textAreaComponent.getValue() === "";
35855
+ getValue() {
35856
+ const indices = this.multipleDropdownComponent.getValue().map((str) => parseInt(str, 10));
35857
+ return indices.map((index2) => this.values[index2]).filter((value) => value !== void 0);
36059
35858
  }
36060
35859
  /**
36061
- * Adds a change listener to the component.
35860
+ * Sets the callback function to be called when the component is changed.
36062
35861
  *
36063
- * @param callback - The callback to call when the value changes.
35862
+ * @param callback - The callback function to be called when the component is changed.
36064
35863
  * @returns The component.
36065
35864
  */
36066
35865
  onChange(callback) {
@@ -36068,7 +35867,7 @@ var MultipleTextComponent = class extends import_obsidian146.ValueComponent {
36068
35867
  callback(this.getValue());
36069
35868
  };
36070
35869
  this.simulateChangeCallback = changeHandler;
36071
- this.textAreaComponent.onChange(changeHandler);
35870
+ this.multipleDropdownComponent.onChange(changeHandler);
36072
35871
  return this;
36073
35872
  }
36074
35873
  /**
@@ -36079,27 +35878,7 @@ var MultipleTextComponent = class extends import_obsidian146.ValueComponent {
36079
35878
  */
36080
35879
  setDisabled(disabled) {
36081
35880
  super.setDisabled(disabled);
36082
- this.textAreaComponent.setDisabled(disabled);
36083
- return this;
36084
- }
36085
- /**
36086
- * Sets the placeholder of the component.
36087
- *
36088
- * @param placeholder - The placeholder to set.
36089
- * @returns The component.
36090
- */
36091
- setPlaceholder(placeholder) {
36092
- this.textAreaComponent.setPlaceholder(placeholder);
36093
- return this;
36094
- }
36095
- /**
36096
- * Sets the placeholder value of the component.
36097
- *
36098
- * @param placeholderValue - The placeholder value to set.
36099
- * @returns The component.
36100
- */
36101
- setPlaceholderValue(placeholderValue) {
36102
- this.setPlaceholder(this.valueToString(placeholderValue));
35881
+ this.multipleDropdownComponent.setDisabled(disabled);
36103
35882
  return this;
36104
35883
  }
36105
35884
  /**
@@ -36109,7 +35888,8 @@ var MultipleTextComponent = class extends import_obsidian146.ValueComponent {
36109
35888
  * @returns The component.
36110
35889
  */
36111
35890
  setValue(value) {
36112
- this.textAreaComponent.setValue(this.valueToString(value));
35891
+ const indices = value.map((v) => this.values.indexOf(v)).filter((index2) => index2 !== -1);
35892
+ this.multipleDropdownComponent.setValue(indices.map((index2) => String(index2)));
36113
35893
  return this;
36114
35894
  }
36115
35895
  /**
@@ -36120,41 +35900,32 @@ var MultipleTextComponent = class extends import_obsidian146.ValueComponent {
36120
35900
  simulateChange__() {
36121
35901
  this.simulateChangeCallback?.();
36122
35902
  }
36123
- /**
36124
- * Converts the value to the string shown in the text area. Subclasses can override to customize the serialization.
36125
- *
36126
- * @param value - The value to convert.
36127
- * @returns The string representation of the value.
36128
- */
36129
- valueToString(value) {
36130
- return value.join("\n");
36131
- }
36132
35903
  };
36133
35904
 
36134
- // src/obsidian/setting-components/number-component.ts
36135
- var number_component_exports = {};
36136
- __export(number_component_exports, {
36137
- NumberComponent: () => NumberComponent
35905
+ // src/obsidian/setting-components/url-component.ts
35906
+ var url_component_exports = {};
35907
+ __export(url_component_exports, {
35908
+ UrlComponent: () => UrlComponent
36138
35909
  });
36139
35910
  init_css_class();
36140
- var NumberComponent = class extends TypedRangeTextComponent {
35911
+ var UrlComponent = class extends TypedTextComponent {
36141
35912
  /**
36142
- * Creates a new number component.
35913
+ * Creates a new Url component.
36143
35914
  *
36144
35915
  * @param containerEl - The container element of the component.
36145
35916
  */
36146
35917
  constructor(containerEl) {
36147
35918
  super({
36148
35919
  containerEl,
36149
- cssClass: "number-component" /* NumberComponent */,
36150
- type: "number"
35920
+ cssClass: "url-component" /* UrlComponent */,
35921
+ type: "url"
36151
35922
  });
36152
35923
  }
36153
35924
  /**
36154
35925
  * Empties the component.
36155
35926
  */
36156
35927
  empty() {
36157
- this.textComponent.setValue("");
35928
+ this.setValue("");
36158
35929
  }
36159
35930
  /**
36160
35931
  * Checks if the component is empty.
@@ -36162,17 +35933,7 @@ var NumberComponent = class extends TypedRangeTextComponent {
36162
35933
  * @returns `true` if the component is empty, `false` otherwise.
36163
35934
  */
36164
35935
  isEmpty() {
36165
- return this.textComponent.getValue() === "";
36166
- }
36167
- /**
36168
- * Sets the placeholder of the component.
36169
- *
36170
- * @param placeholder - The placeholder to set.
36171
- * @returns The component.
36172
- */
36173
- setPlaceholder(placeholder) {
36174
- this.textComponent.setPlaceholder(placeholder);
36175
- return this;
35936
+ return this.getValue() === "";
36176
35937
  }
36177
35938
  /**
36178
35939
  * Sets the placeholder value of the component.
@@ -36181,808 +35942,1269 @@ var NumberComponent = class extends TypedRangeTextComponent {
36181
35942
  * @returns The component.
36182
35943
  */
36183
35944
  setPlaceholderValue(placeholderValue) {
36184
- this.textComponent.setPlaceholder(this.valueToString(placeholderValue));
35945
+ this.textComponent.setPlaceholder(placeholderValue);
36185
35946
  return this;
36186
35947
  }
36187
35948
  /**
36188
- * Converts a string to a number.
35949
+ * Converts a string to an url.
36189
35950
  *
36190
35951
  * @param str - The string to convert.
36191
- * @returns The number.
35952
+ * @returns The url.
36192
35953
  */
36193
35954
  valueFromString(str) {
36194
- return parseInt(str, 10);
35955
+ return str;
36195
35956
  }
36196
35957
  };
36197
35958
 
36198
- // src/obsidian/setting-components/password-component.ts
36199
- var password_component_exports = {};
36200
- __export(password_component_exports, {
36201
- PasswordComponent: () => PasswordComponent
35959
+ // src/obsidian/setting-components/week-component.ts
35960
+ var week_component_exports = {};
35961
+ __export(week_component_exports, {
35962
+ WeekComponent: () => WeekComponent
36202
35963
  });
35964
+ var import_obsidian143 = require("obsidian");
36203
35965
  init_css_class();
36204
- var PasswordComponent = class extends TypedTextComponent {
35966
+ var moment6 = extractDefaultExportInterop(import_obsidian143.moment);
35967
+ var DATE_FORMAT3 = "YYYY-[W]WW";
35968
+ var WeekComponent = class extends TypedRangeTextComponent {
36205
35969
  /**
36206
- * Creates a new password component.
35970
+ * Creates a new Week component.
36207
35971
  *
36208
35972
  * @param containerEl - The container element of the component.
36209
35973
  */
36210
35974
  constructor(containerEl) {
36211
35975
  super({
36212
35976
  containerEl,
36213
- cssClass: "password-component" /* PasswordComponent */,
36214
- type: "password"
35977
+ cssClass: "week-component" /* WeekComponent */,
35978
+ type: "week"
36215
35979
  });
36216
35980
  }
36217
35981
  /**
36218
- * Sets the placeholder value of the component.
35982
+ * Converts a string to a Week.
36219
35983
  *
36220
- * @param placeholder - The placeholder to set.
36221
- * @returns The component.
35984
+ * @param str - The string to convert.
35985
+ * @returns The week.
36222
35986
  */
36223
- setPlaceholder(placeholder) {
36224
- this.textComponent.setPlaceholder(placeholder);
36225
- return this;
35987
+ valueFromString(str) {
35988
+ const parsed = moment6(str, DATE_FORMAT3);
35989
+ if (!parsed.isValid()) {
35990
+ throw new Error("Invalid week");
35991
+ }
35992
+ return {
35993
+ weekNumber: parsed.isoWeek(),
35994
+ year: parsed.year()
35995
+ };
36226
35996
  }
36227
35997
  /**
36228
- * Gets the value from a string.
35998
+ * Converts a week to a string.
36229
35999
  *
36230
- * @param str - The string to get the value from.
36231
- * @returns The value from the string.
36000
+ * @param value - The week to convert.
36001
+ * @returns The string.
36232
36002
  */
36233
- valueFromString(str) {
36234
- return str;
36003
+ valueToString(value) {
36004
+ const date = moment6().year(value.year).isoWeek(value.weekNumber);
36005
+ return date.format(DATE_FORMAT3);
36235
36006
  }
36236
36007
  };
36237
36008
 
36238
- // src/obsidian/setting-components/telephone-component.ts
36239
- var telephone_component_exports = {};
36240
- __export(telephone_component_exports, {
36241
- TelephoneComponent: () => TelephoneComponent
36242
- });
36243
- init_css_class();
36244
- var TelephoneComponent = class extends TypedTextComponent {
36009
+ // src/obsidian/setting-ex.ts
36010
+ var SettingEx = class extends import_obsidian144.Setting {
36245
36011
  /**
36246
- * Creates a new telephone component.
36012
+ * Adds a {@link CheckboxComponent} to the setting.
36247
36013
  *
36248
- * @param containerEl - The container element of the component.
36014
+ * @param cb - The callback to call with the component.
36015
+ * @returns The setting instance.
36249
36016
  */
36250
- constructor(containerEl) {
36251
- super({
36252
- containerEl,
36253
- cssClass: "telephone-component" /* TelephoneComponent */,
36254
- type: "tel"
36255
- });
36017
+ addCheckbox(cb) {
36018
+ return this.addComponentClass(CheckboxComponent, cb);
36256
36019
  }
36257
36020
  /**
36258
- * Empties the component.
36021
+ * Adds a {@link CodeHighlighterComponent} to the setting.
36022
+ *
36023
+ * @param cb - The callback to call with the component.
36024
+ * @returns The setting instance.
36259
36025
  */
36260
- empty() {
36261
- this.textComponent.setValue("");
36026
+ addCodeHighlighter(cb) {
36027
+ return this.addComponentClass(CodeHighlighterComponent, cb);
36262
36028
  }
36263
36029
  /**
36264
- * Checks if the component is empty.
36030
+ * Adds a component to the setting.
36265
36031
  *
36266
- * @returns `true` if the component is empty, `false` otherwise.
36032
+ * @typeParam T - The type of the component to add.
36033
+ * @param componentClass - The class of the component to add.
36034
+ * @param cb - The callback to call with the component.
36035
+ * @returns The setting instance.
36267
36036
  */
36268
- isEmpty() {
36269
- return this.textComponent.getValue() === "";
36037
+ addComponentClass(componentClass, cb) {
36038
+ return this.addComponent((el) => {
36039
+ const component = new componentClass(el);
36040
+ cb(component);
36041
+ return component;
36042
+ });
36270
36043
  }
36271
36044
  /**
36272
- * Sets the placeholder value of the component.
36045
+ * Adds a {@link DateComponent} to the setting.
36273
36046
  *
36274
- * @param placeholderValue - The placeholder value to set.
36275
- * @returns The component.
36047
+ * @param cb - The callback to call with the component.
36048
+ * @returns The setting instance.
36276
36049
  */
36277
- setPlaceholderValue(placeholderValue) {
36278
- this.textComponent.setPlaceholder(placeholderValue);
36279
- return this;
36050
+ addDate(cb) {
36051
+ return this.addComponentClass(DateComponent, cb);
36280
36052
  }
36281
36053
  /**
36282
- * Gets the value from a string.
36054
+ * Adds a {@link DateTimeComponent} to the setting.
36283
36055
  *
36284
- * @param str - The string to get the value from.
36285
- * @returns The value from the string.
36056
+ * @param cb - The callback to call with the component.
36057
+ * @returns The setting instance.
36286
36058
  */
36287
- valueFromString(str) {
36288
- return str;
36059
+ addDateTime(cb) {
36060
+ return this.addComponentClass(DateTimeComponent, cb);
36289
36061
  }
36290
- };
36291
-
36292
- // src/obsidian/setting-components/time-component.ts
36293
- var time_component_exports = {};
36294
- __export(time_component_exports, {
36295
- TimeComponent: () => TimeComponent
36296
- });
36297
- var import_obsidian147 = require("obsidian");
36298
- init_css_class();
36299
- var TimeComponent = class extends TypedRangeTextComponent {
36300
36062
  /**
36301
- * Creates a new time component.
36063
+ * Adds an {@link EmailComponent} to the setting.
36302
36064
  *
36303
- * @param containerEl - The container element of the component.
36065
+ * @param cb - The callback to call with the component.
36066
+ * @returns The setting instance.
36304
36067
  */
36305
- constructor(containerEl) {
36306
- super({
36307
- containerEl,
36308
- cssClass: "time-component" /* TimeComponent */,
36309
- type: "time"
36310
- });
36068
+ addEmail(cb) {
36069
+ return this.addComponentClass(EmailComponent, cb);
36311
36070
  }
36312
36071
  /**
36313
- * Converts a string to a time.
36072
+ * Adds a {@link FileComponent} to the setting.
36314
36073
  *
36315
- * @param str - The string to convert.
36316
- * @returns The date.
36074
+ * @param cb - The callback to call with the component.
36075
+ * @returns The setting instance.
36317
36076
  */
36318
- valueFromString(str) {
36319
- return import_obsidian147.moment.duration(str);
36077
+ addFile(cb) {
36078
+ return this.addComponentClass(FileComponent, cb);
36320
36079
  }
36321
36080
  /**
36322
- * Converts a time to a string.
36081
+ * Adds a {@link MonthComponent} to the setting.
36323
36082
  *
36324
- * @param value - The time to convert.
36325
- * @returns The string.
36083
+ * @param cb - The callback to call with the component.
36084
+ * @returns The setting instance.
36326
36085
  */
36327
- valueToString(value) {
36328
- let format2;
36329
- if (value.milliseconds() > 0) {
36330
- format2 = "HH:mm:ss.SSS";
36331
- } else if (value.seconds() > 0) {
36332
- format2 = "HH:mm:ss";
36333
- } else {
36334
- format2 = "HH:mm";
36335
- }
36336
- return import_obsidian147.moment.utc(value.asMilliseconds()).format(format2);
36086
+ addMonth(cb) {
36087
+ return this.addComponentClass(MonthComponent, cb);
36337
36088
  }
36338
- };
36339
-
36340
- // src/obsidian/setting-components/tri-state-checkbox-component.ts
36341
- var tri_state_checkbox_component_exports = {};
36342
- __export(tri_state_checkbox_component_exports, {
36343
- TriStateCheckboxComponent: () => TriStateCheckboxComponent
36344
- });
36345
- var import_obsidian148 = require("obsidian");
36346
- init_css_class();
36347
- init_plugin_context();
36348
- var TriStateCheckboxComponent = class extends import_obsidian148.ValueComponent {
36349
36089
  /**
36350
- * An input element of the checkbox.
36351
- */
36352
- inputEl;
36353
- /**
36354
- * A validator element of the checkbox.
36090
+ * Adds a {@link MultipleDropdownComponent} to the setting.
36355
36091
  *
36356
- * @returns The validator element.
36092
+ * @param cb - The callback to call with the component.
36093
+ * @returns The setting instance.
36357
36094
  */
36358
- get validatorEl() {
36359
- return this.inputEl;
36095
+ addMultipleDropdown(cb) {
36096
+ return this.addComponentClass(MultipleDropdownComponent, cb);
36360
36097
  }
36361
- changeCallback;
36362
36098
  /**
36363
- * Creates a new tri-state checkbox component.
36099
+ * Adds a {@link MultipleEmailComponent} to the setting.
36364
36100
  *
36365
- * @param containerEl - The container element.
36101
+ * @param cb - The callback to call with the component.
36102
+ * @returns The setting instance.
36366
36103
  */
36367
- constructor(containerEl) {
36368
- super();
36369
- addPluginCssClasses(containerEl, "tri-state-checkbox-component" /* TriStateCheckboxComponent */);
36370
- this.inputEl = containerEl.createEl("input", { type: "checkbox" });
36371
- this.inputEl.addEventListener("change", this.onChanged.bind(this));
36104
+ addMultipleEmail(cb) {
36105
+ return this.addComponentClass(MultipleEmailComponent, cb);
36372
36106
  }
36373
36107
  /**
36374
- * Gets the value of the checkbox.
36108
+ * Adds a {@link MultipleFileComponent} to the setting.
36375
36109
  *
36376
- * @returns The value of the checkbox.
36110
+ * @param cb - The callback to call with the component.
36111
+ * @returns The setting instance.
36377
36112
  */
36378
- getValue() {
36379
- return this.inputEl.indeterminate ? null : this.inputEl.checked;
36113
+ addMultipleFile(cb) {
36114
+ return this.addComponentClass(MultipleFileComponent, cb);
36380
36115
  }
36381
36116
  /**
36382
- * Sets the callback to be called when the checkbox is changed.
36117
+ * Adds a {@link MultipleTextComponent} to the setting.
36383
36118
  *
36384
- * @param callback - The callback to be called when the checkbox is changed.
36385
- * @returns The component.
36119
+ * @param cb - The callback to call with the component.
36120
+ * @returns The setting instance.
36386
36121
  */
36387
- onChange(callback) {
36388
- this.changeCallback = callback;
36389
- return this;
36122
+ addMultipleText(cb) {
36123
+ return this.addComponentClass(MultipleTextComponent, cb);
36390
36124
  }
36391
36125
  /**
36392
- * Called when the checkbox is changed.
36126
+ * Adds a {@link NumberComponent} to the setting.
36127
+ *
36128
+ * @param cb - The callback to call with the component.
36129
+ * @returns The setting instance.
36393
36130
  */
36394
- onChanged() {
36395
- this.changeCallback?.(this.getValue());
36131
+ addNumber(cb) {
36132
+ return this.addComponentClass(NumberComponent, cb);
36396
36133
  }
36397
36134
  /**
36398
- * Sets the disabled state of the checkbox.
36135
+ * Adds a {@link PasswordComponent} to the setting.
36399
36136
  *
36400
- * @param disabled - The disabled state of the checkbox.
36401
- * @returns The component.
36137
+ * @param cb - The callback to call with the component.
36138
+ * @returns The setting instance.
36402
36139
  */
36403
- setDisabled(disabled) {
36404
- super.setDisabled(disabled);
36405
- this.inputEl.disabled = disabled;
36406
- return this;
36140
+ addPassword(cb) {
36141
+ return this.addComponentClass(PasswordComponent, cb);
36407
36142
  }
36408
36143
  /**
36409
- * Sets the value of the checkbox.
36144
+ * Adds a {@link TelephoneComponent} to the setting.
36410
36145
  *
36411
- * @param value - The value to set the checkbox to.
36412
- * @returns The component.
36146
+ * @param cb - The callback to call with the component.
36147
+ * @returns The setting instance.
36413
36148
  */
36414
- setValue(value) {
36415
- this.inputEl.indeterminate = value === null;
36416
- this.inputEl.checked = value ?? false;
36417
- return this;
36149
+ addTelephone(cb) {
36150
+ return this.addComponentClass(TelephoneComponent, cb);
36418
36151
  }
36419
- };
36420
-
36421
- // src/obsidian/setting-components/typed-dropdown-component.ts
36422
- var typed_dropdown_component_exports = {};
36423
- __export(typed_dropdown_component_exports, {
36424
- TypedDropdownComponent: () => TypedDropdownComponent
36425
- });
36426
- var import_obsidian149 = require("obsidian");
36427
- init_css_class();
36428
- init_plugin_context();
36429
- var TypedDropdownComponent = class extends import_obsidian149.ValueComponent {
36430
36152
  /**
36431
- * A select element of the component.
36153
+ * Adds a {@link TimeComponent} to the setting.
36432
36154
  *
36433
- * @returns The select element.
36155
+ * @param cb - The callback to call with the component.
36156
+ * @returns The setting instance.
36434
36157
  */
36435
- get selectEl() {
36436
- return this.dropdownComponent.selectEl;
36158
+ addTime(cb) {
36159
+ return this.addComponentClass(TimeComponent, cb);
36437
36160
  }
36438
36161
  /**
36439
- * A validator element of the component.
36162
+ * Adds a {@link TriStateCheckboxComponent} to the setting.
36440
36163
  *
36441
- * @returns The validator element.
36164
+ * @param cb - The callback to call with the component.
36165
+ * @returns The setting instance.
36442
36166
  */
36443
- get validatorEl() {
36444
- return this.selectEl;
36167
+ addTriStateCheckbox(cb) {
36168
+ return this.addComponentClass(TriStateCheckboxComponent, cb);
36445
36169
  }
36446
36170
  /**
36447
- * The inner dropdown component.
36448
- */
36449
- dropdownComponent;
36450
- /**
36451
- * The list of selectable option values, indexed by their position in the dropdown.
36171
+ * Adds a {@link TypedDropdownComponent} to the setting.
36172
+ *
36173
+ * @typeParam T - The type of the dropdown items.
36174
+ * @param cb - The callback to call with the component.
36175
+ * @returns The setting instance.
36452
36176
  */
36453
- values = [];
36454
- simulateChangeCallback;
36177
+ addTypedDropdown(cb) {
36178
+ return this.addComponentClass(TypedDropdownComponent, cb);
36179
+ }
36455
36180
  /**
36456
- * Creates a new multiple dropdown component.
36181
+ * Adds a {@link TypedMultipleDropdownComponent} to the setting.
36457
36182
  *
36458
- * @param containerEl - The container element of the component.
36183
+ * @typeParam T - The type of the items in the dropdown.
36184
+ * @param cb - The callback to call with the component.
36185
+ * @returns The setting instance.
36459
36186
  */
36460
- constructor(containerEl) {
36461
- super();
36462
- this.dropdownComponent = new import_obsidian149.DropdownComponent(containerEl);
36463
- addPluginCssClasses(containerEl, "typed-dropdown-component" /* TypedDropdownComponent */);
36187
+ addTypedMultipleDropdown(cb) {
36188
+ return this.addComponentClass(TypedMultipleDropdownComponent, cb);
36464
36189
  }
36465
36190
  /**
36466
- * Adds an option to the dropdown.
36191
+ * Adds an {@link UrlComponent} to the setting.
36467
36192
  *
36468
- * @param value - The value of the option.
36469
- * @param display - The display text of the option.
36470
- * @returns The component.
36193
+ * @param cb - The callback to call with the component.
36194
+ * @returns The setting instance.
36471
36195
  */
36472
- addOption(value, display) {
36473
- let index2 = this.values.indexOf(value);
36474
- if (index2 === -1) {
36475
- this.values.push(value);
36476
- index2 = this.values.length - 1;
36477
- }
36478
- this.dropdownComponent.addOption(String(index2), display);
36479
- return this;
36196
+ addUrl(cb) {
36197
+ return this.addComponentClass(UrlComponent, cb);
36480
36198
  }
36481
36199
  /**
36482
- * Adds multiple options to the dropdown.
36200
+ * Adds a {@link WeekComponent} to the setting.
36483
36201
  *
36484
- * @param options - The options to add.
36485
- * @returns The component.
36486
- */
36487
- addOptions(options) {
36488
- for (const [value, display] of options.entries()) {
36489
- this.addOption(value, display);
36490
- }
36491
- return this;
36492
- }
36493
- /**
36494
- * Gets the value of the component.
36495
- *
36496
- * @returns The value of the component.
36497
- */
36498
- getValue() {
36499
- return this.values[this.dropdownComponent.selectEl.selectedIndex] ?? null;
36500
- }
36501
- /**
36502
- * Sets the callback function to be called when the component is changed.
36503
- *
36504
- * @param callback - The callback function to be called when the component is changed.
36505
- * @returns The component.
36506
- */
36507
- onChange(callback) {
36508
- const changeHandler = () => {
36509
- callback(this.getValue());
36510
- };
36511
- this.simulateChangeCallback = changeHandler;
36512
- this.dropdownComponent.onChange(changeHandler);
36513
- return this;
36514
- }
36515
- /**
36516
- * Sets the disabled state of the component.
36517
- *
36518
- * @param disabled - The disabled state to set.
36519
- * @returns The component.
36520
- */
36521
- setDisabled(disabled) {
36522
- super.setDisabled(disabled);
36523
- this.dropdownComponent.setDisabled(disabled);
36524
- return this;
36525
- }
36526
- /**
36527
- * Sets the value of the component.
36528
- *
36529
- * @param value - The value to set.
36530
- * @returns The component.
36531
- */
36532
- setValue(value) {
36533
- const index2 = value === null ? -1 : this.values.indexOf(value);
36534
- this.dropdownComponent.selectEl.selectedIndex = index2;
36535
- return this;
36536
- }
36537
- /**
36538
- * Simulate a change event.
36539
- *
36540
- * @deprecated Use only from tests to simulate a change event.
36202
+ * @param cb - The callback to call with the component.
36203
+ * @returns The setting instance.
36541
36204
  */
36542
- simulateChange__() {
36543
- this.simulateChangeCallback?.();
36205
+ addWeek(cb) {
36206
+ return this.addComponentClass(WeekComponent, cb);
36544
36207
  }
36545
36208
  };
36209
+ function adoptSettingEx(setting) {
36210
+ if (setting instanceof SettingEx) {
36211
+ return setting;
36212
+ }
36213
+ Object.setPrototypeOf(setting, SettingEx.prototype);
36214
+ return castTo(setting);
36215
+ }
36546
36216
 
36547
- // src/obsidian/setting-components/typed-multiple-dropdown-component.ts
36548
- var typed_multiple_dropdown_component_exports = {};
36549
- __export(typed_multiple_dropdown_component_exports, {
36550
- TypedMultipleDropdownComponent: () => TypedMultipleDropdownComponent
36217
+ // src/obsidian/validation.ts
36218
+ var validation_exports = {};
36219
+ __export(validation_exports, {
36220
+ OBSIDIAN_UNSAFE_FILENAME_CHARS: () => OBSIDIAN_UNSAFE_FILENAME_CHARS,
36221
+ UNIX_UNSAFE_PATH_CHARS: () => UNIX_UNSAFE_PATH_CHARS,
36222
+ WINDOWS_UNSAFE_PATH_CHARS: () => WINDOWS_UNSAFE_PATH_CHARS,
36223
+ getOsAndObsidianUnsafePathCharsRegExp: () => getOsAndObsidianUnsafePathCharsRegExp,
36224
+ getOsUnsafePathCharsRegExp: () => getOsUnsafePathCharsRegExp,
36225
+ isValidationMessageHolder: () => isValidationMessageHolder
36551
36226
  });
36552
- var import_obsidian150 = require("obsidian");
36553
- init_css_class();
36227
+ var import_obsidian145 = require("obsidian");
36228
+ init_reg_exp();
36229
+ function isValidationMessageHolder(value) {
36230
+ return value.validationMessage !== void 0;
36231
+ }
36232
+ var OBSIDIAN_UNSAFE_FILENAME_CHARS = /[#^[\]|]/g;
36233
+ var WINDOWS_UNSAFE_PATH_CHARS = /[*\\/<>:|?"]/g;
36234
+ var UNIX_UNSAFE_PATH_CHARS = /[\0/]/g;
36235
+ function getOsAndObsidianUnsafePathCharsRegExp(isWindows) {
36236
+ return oneOf([
36237
+ getOsUnsafePathCharsRegExp(isWindows),
36238
+ OBSIDIAN_UNSAFE_FILENAME_CHARS
36239
+ ]);
36240
+ }
36241
+ function getOsUnsafePathCharsRegExp(isWindows) {
36242
+ isWindows ??= import_obsidian145.Platform.isWin;
36243
+ return isWindows ? WINDOWS_UNSAFE_PATH_CHARS : UNIX_UNSAFE_PATH_CHARS;
36244
+ }
36245
+
36246
+ // src/obsidian/plugin/plugin-settings-tab.ts
36554
36247
  init_plugin_context();
36555
- var TypedMultipleDropdownComponent = class extends import_obsidian150.ValueComponent {
36556
- /**
36557
- * A select element of the component.
36558
- *
36559
- * @returns The select element.
36560
- */
36561
- get selectEl() {
36562
- return this.multipleDropdownComponent.selectEl;
36563
- }
36564
- /**
36565
- * A validator element of the component.
36566
- *
36567
- * @returns The validator element.
36568
- */
36569
- get validatorEl() {
36570
- return this.selectEl;
36571
- }
36572
- /**
36573
- * The inner multiple dropdown component.
36574
- */
36575
- multipleDropdownComponent;
36576
- /**
36577
- * The list of selectable option values, indexed by their position in the dropdown.
36578
- */
36579
- values = [];
36580
- simulateChangeCallback;
36248
+ var SAVE_TO_FILE_CONTEXT = "PluginSettingsTab";
36249
+ var PluginSettingsTabEventsComponent = class extends ComponentEx {
36250
+ params;
36581
36251
  /**
36582
- * Creates a new multiple dropdown component.
36252
+ * Creates a new component.
36583
36253
  *
36584
- * @param containerEl - The container element of the component.
36254
+ * @param params - The params.
36585
36255
  */
36586
- constructor(containerEl) {
36256
+ constructor(params) {
36587
36257
  super();
36588
- this.multipleDropdownComponent = new MultipleDropdownComponent(containerEl);
36589
- addPluginCssClasses(containerEl, "typed-multiple-dropdown-component" /* TypedMultipleDropdownComponent */);
36590
- }
36591
- /**
36592
- * Adds an option to the dropdown.
36593
- *
36594
- * @param value - The value of the option.
36595
- * @param display - The display text of the option.
36596
- * @returns The component.
36597
- */
36598
- addOption(value, display) {
36599
- let index2 = this.values.indexOf(value);
36600
- if (index2 === -1) {
36601
- this.values.push(value);
36602
- index2 = this.values.length - 1;
36603
- }
36604
- this.multipleDropdownComponent.addOption(String(index2), display);
36605
- return this;
36606
- }
36607
- /**
36608
- * Adds multiple options to the dropdown.
36609
- *
36610
- * @param options - The options to add.
36611
- * @returns The component.
36612
- */
36613
- addOptions(options) {
36614
- for (const [value, display] of options.entries()) {
36615
- this.addOption(value, display);
36616
- }
36617
- return this;
36258
+ this.params = params;
36618
36259
  }
36619
36260
  /**
36620
- * Gets the value of the component.
36621
- *
36622
- * @returns The value of the component.
36261
+ * Subscribes to the settings component's events.
36623
36262
  */
36624
- getValue() {
36625
- const indices = this.multipleDropdownComponent.getValue().map((str) => parseInt(str, 10));
36626
- return indices.map((index2) => this.values[index2]).filter((value) => value !== void 0);
36263
+ onload() {
36264
+ super.onload();
36265
+ const { pluginSettingsComponent } = this.params;
36266
+ registerAsyncEvent(this, pluginSettingsComponent.on("loadSettings", (loadedState, isInitialLoad) => this.params.onLoadSettings(loadedState, isInitialLoad)));
36267
+ registerAsyncEvent(this, pluginSettingsComponent.on("saveSettings", (newState, oldState, context) => this.params.onSaveSettings(newState, oldState, context)));
36627
36268
  }
36269
+ };
36270
+ var PluginSettingsTabBase = class extends mixinAsyncEvents()(import_obsidian146.PluginSettingTab) {
36628
36271
  /**
36629
- * Sets the callback function to be called when the component is changed.
36272
+ * Whether the plugin settings tab is open.
36630
36273
  *
36631
- * @param callback - The callback function to be called when the component is changed.
36632
- * @returns The component.
36274
+ * @returns Whether the plugin settings tab is open.
36633
36275
  */
36634
- onChange(callback) {
36635
- const changeHandler = () => {
36636
- callback(this.getValue());
36637
- };
36638
- this.simulateChangeCallback = changeHandler;
36639
- this.multipleDropdownComponent.onChange(changeHandler);
36640
- return this;
36276
+ get isOpen() {
36277
+ return this._isOpen;
36641
36278
  }
36642
36279
  /**
36643
- * Sets the disabled state of the component.
36644
- *
36645
- * @param disabled - The disabled state to set.
36646
- * @returns The component.
36280
+ * The settings manager.
36647
36281
  */
36648
- setDisabled(disabled) {
36649
- super.setDisabled(disabled);
36650
- this.multipleDropdownComponent.setDisabled(disabled);
36651
- return this;
36652
- }
36282
+ pluginSettingsComponent;
36653
36283
  /**
36654
- * Sets the value of the component.
36284
+ * A debounce timeout for saving settings.
36655
36285
  *
36656
- * @param value - The value to set.
36657
- * @returns The component.
36286
+ * @returns The debounce timeout for saving settings.
36658
36287
  */
36659
- setValue(value) {
36660
- const indices = value.map((v) => this.values.indexOf(v)).filter((index2) => index2 !== -1);
36661
- this.multipleDropdownComponent.setValue(indices.map((index2) => String(index2)));
36662
- return this;
36288
+ get saveSettingsDebounceTimeoutInMilliseconds() {
36289
+ const DEFAULT = 2e3;
36290
+ return DEFAULT;
36663
36291
  }
36664
- /**
36665
- * Simulate a change event.
36666
- *
36667
- * @deprecated Use only from tests to simulate a change event.
36668
- */
36669
- simulateChange__() {
36670
- this.simulateChangeCallback?.();
36292
+ _isOpen = false;
36293
+ component;
36294
+ currentRenderComponent = null;
36295
+ saveSettingsDebounced;
36296
+ get pluginSettings() {
36297
+ return this.pluginSettingsComponent.settingsState.inputValues;
36671
36298
  }
36672
- };
36673
-
36674
- // src/obsidian/setting-components/url-component.ts
36675
- var url_component_exports = {};
36676
- __export(url_component_exports, {
36677
- UrlComponent: () => UrlComponent
36678
- });
36679
- init_css_class();
36680
- var UrlComponent = class extends TypedTextComponent {
36681
36299
  /**
36682
- * Creates a new Url component.
36300
+ * Creates a new plugin settings tab.
36683
36301
  *
36684
- * @param containerEl - The container element of the component.
36302
+ * @param params - The params.
36685
36303
  */
36686
- constructor(containerEl) {
36687
- super({
36688
- containerEl,
36689
- cssClass: "url-component" /* UrlComponent */,
36690
- type: "url"
36304
+ constructor(params) {
36305
+ super(params.plugin.app, params.plugin);
36306
+ this.pluginSettingsComponent = params.pluginSettingsComponent;
36307
+ addPluginCssClasses(this.containerEl, "plugin-settings-tab" /* PluginSettingsTab */);
36308
+ this.saveSettingsDebounced = (0, import_obsidian146.debounce)(
36309
+ convertAsyncToSync(() => this.pluginSettingsComponent.saveToFile(SAVE_TO_FILE_CONTEXT)),
36310
+ this.saveSettingsDebounceTimeoutInMilliseconds
36311
+ );
36312
+ this.component = new PluginSettingsTabEventsComponent({
36313
+ onLoadSettings: (loadedState, isInitialLoad) => this.onLoadSettings(loadedState, isInitialLoad),
36314
+ onSaveSettings: (newState, oldState, context) => this.onSaveSettings({ context, newState, oldState }),
36315
+ pluginSettingsComponent: this.pluginSettingsComponent
36691
36316
  });
36692
36317
  }
36693
36318
  /**
36694
- * Empties the component.
36695
- */
36696
- empty() {
36697
- this.setValue("");
36698
- }
36699
- /**
36700
- * Checks if the component is empty.
36319
+ * Binds a value component to a plugin setting.
36701
36320
  *
36702
- * @returns `true` if the component is empty, `false` otherwise.
36703
- */
36704
- isEmpty() {
36705
- return this.getValue() === "";
36321
+ * @typeParam UIValue - The type of the value of the UI component.
36322
+ * @typeParam TValueComponent - The type of the value component.
36323
+ * @typeParam PropertyName - The property name of the plugin settings to bind to.
36324
+ * @param params - The params for binding the value component.
36325
+ * @returns The value component.
36326
+ */
36327
+ bind(params) {
36328
+ const {
36329
+ propertyName,
36330
+ valueComponent,
36331
+ ...options
36332
+ } = params;
36333
+ const DEFAULT_OPTIONS = {
36334
+ componentToPluginSettingsValueConverter: (value) => value,
36335
+ onChanged: noop,
36336
+ pluginSettingsToComponentValueConverter: (value) => value,
36337
+ shouldResetSettingWhenComponentIsEmpty: true,
36338
+ shouldShowPlaceholderForDefaultValues: true,
36339
+ shouldShowValidationMessage: true
36340
+ };
36341
+ const optionsExt = { ...DEFAULT_OPTIONS, ...options };
36342
+ const validatorEl = getValidatorComponent(valueComponent)?.validatorEl;
36343
+ const textBasedComponent = getTextBasedComponentValue(valueComponent);
36344
+ const readonlyValue = this.getPluginSettingsProperty(propertyName);
36345
+ const defaults = this.pluginSettingsComponent.defaultSettings;
36346
+ const defaultValue = defaults[propertyName];
36347
+ const defaultComponentValue = optionsExt.pluginSettingsToComponentValueConverter(defaultValue);
36348
+ textBasedComponent?.setPlaceholderValue(defaultComponentValue);
36349
+ let validationMessage;
36350
+ let tooltipEl = null;
36351
+ let tooltipContentEl = null;
36352
+ if (validatorEl) {
36353
+ const wrapper = ensureWrapped(validatorEl);
36354
+ tooltipEl = wrapper.createDiv();
36355
+ addPluginCssClasses(tooltipEl, ["tooltip" /* Tooltip */, "tooltip-validator" /* TooltipValidator */]);
36356
+ tooltipContentEl = tooltipEl.createSpan();
36357
+ const tooltipArrowEl = tooltipEl.createDiv();
36358
+ addPluginCssClasses(tooltipArrowEl, "tooltip-arrow" /* TooltipArrow */);
36359
+ tooltipEl.hide();
36360
+ wrapper.appendChild(tooltipEl);
36361
+ }
36362
+ registerAsyncEvent(
36363
+ this.getRenderComponent(),
36364
+ this.on("validationMessageChanged", (anotherPropertyName, anotherValidationMessage) => {
36365
+ if (propertyName !== anotherPropertyName) {
36366
+ return;
36367
+ }
36368
+ validationMessage = anotherValidationMessage;
36369
+ updateValidatorElDebounced();
36370
+ })
36371
+ );
36372
+ let shouldEmptyOnBlur = false;
36373
+ let shouldRevertToDefaultValueOnBlur = false;
36374
+ if (textBasedComponent && optionsExt.shouldShowPlaceholderForDefaultValues && deepEqual(readonlyValue, defaultValue)) {
36375
+ textBasedComponent.empty();
36376
+ } else {
36377
+ valueComponent.setValue(optionsExt.pluginSettingsToComponentValueConverter(readonlyValue));
36378
+ }
36379
+ let shouldSkipOnChange = false;
36380
+ const UPDATE_VALIDATOR_EL_TIMEOUT_IN_MILLISECONDS = 100;
36381
+ const updateValidatorElDebounced = (0, import_obsidian146.debounce)(() => {
36382
+ window.requestAnimationFrame(() => {
36383
+ updateValidatorEl();
36384
+ });
36385
+ }, UPDATE_VALIDATOR_EL_TIMEOUT_IN_MILLISECONDS);
36386
+ valueComponent.onChange(convertAsyncToSync(async (uiValue) => {
36387
+ if (shouldSkipOnChange) {
36388
+ shouldSkipOnChange = false;
36389
+ return;
36390
+ }
36391
+ shouldEmptyOnBlur = false;
36392
+ const oldValue = this.getPluginSettingsProperty(propertyName);
36393
+ let newValue = void 0;
36394
+ let shouldSetProperty = true;
36395
+ shouldRevertToDefaultValueOnBlur = !!textBasedComponent?.isEmpty() && optionsExt.shouldResetSettingWhenComponentIsEmpty;
36396
+ if (shouldRevertToDefaultValueOnBlur) {
36397
+ newValue = defaultValue;
36398
+ } else {
36399
+ const convertedValue = optionsExt.componentToPluginSettingsValueConverter(uiValue);
36400
+ if (isValidationMessageHolder(convertedValue)) {
36401
+ validationMessage = convertedValue.validationMessage;
36402
+ shouldSetProperty = false;
36403
+ } else {
36404
+ newValue = convertedValue;
36405
+ }
36406
+ }
36407
+ if (shouldSetProperty) {
36408
+ validationMessage = await this.pluginSettingsComponent.setProperty(propertyName, newValue);
36409
+ if (textBasedComponent && optionsExt.shouldShowPlaceholderForDefaultValues && !textBasedComponent.isEmpty() && deepEqual(newValue, defaultValue)) {
36410
+ shouldEmptyOnBlur = true;
36411
+ }
36412
+ }
36413
+ updateValidatorElDebounced();
36414
+ if (shouldSetProperty) {
36415
+ await optionsExt.onChanged(newValue, oldValue);
36416
+ }
36417
+ this.saveSettingsDebounced();
36418
+ }));
36419
+ validatorEl?.addEventListener("focus", () => {
36420
+ updateValidatorElDebounced();
36421
+ });
36422
+ validatorEl?.addEventListener("blur", () => {
36423
+ updateValidatorElDebounced();
36424
+ });
36425
+ validatorEl?.addEventListener("click", () => {
36426
+ window.requestAnimationFrame(() => {
36427
+ updateValidatorElDebounced();
36428
+ });
36429
+ });
36430
+ const validationMessages = this.pluginSettingsComponent.settingsState.validationMessages;
36431
+ validationMessage = validationMessages[propertyName] ?? "";
36432
+ updateValidatorElDebounced();
36433
+ return valueComponent;
36434
+ function updateValidatorEl() {
36435
+ if (!validatorEl?.isActiveElement()) {
36436
+ if (shouldEmptyOnBlur) {
36437
+ shouldEmptyOnBlur = false;
36438
+ if (!textBasedComponent?.isEmpty()) {
36439
+ shouldSkipOnChange = true;
36440
+ textBasedComponent?.empty();
36441
+ }
36442
+ } else if (shouldRevertToDefaultValueOnBlur) {
36443
+ shouldRevertToDefaultValueOnBlur = false;
36444
+ if (textBasedComponent?.isEmpty()) {
36445
+ shouldSkipOnChange = true;
36446
+ valueComponent.setValue(defaultComponentValue);
36447
+ }
36448
+ }
36449
+ }
36450
+ if (!validatorEl) {
36451
+ return;
36452
+ }
36453
+ assertNonNullable(tooltipContentEl);
36454
+ if (validationMessage === "") {
36455
+ validatorEl.setCustomValidity("");
36456
+ validatorEl.checkValidity();
36457
+ validationMessage = validatorEl.validationMessage;
36458
+ }
36459
+ validatorEl.setCustomValidity(validationMessage);
36460
+ if (optionsExt.shouldShowValidationMessage) {
36461
+ tooltipContentEl.textContent = validationMessage;
36462
+ tooltipEl?.toggle(!!validationMessage);
36463
+ } else if (validationMessage) {
36464
+ (0, import_obsidian146.setTooltip)(validatorEl, validationMessage);
36465
+ }
36466
+ }
36706
36467
  }
36707
36468
  /**
36708
- * Sets the placeholder value of the component.
36709
- *
36710
- * @param placeholderValue - The placeholder value to set.
36711
- * @returns The component.
36469
+ * Renders the plugin settings tab.
36712
36470
  */
36713
- setPlaceholderValue(placeholderValue) {
36714
- this.textComponent.setPlaceholder(placeholderValue);
36715
- return this;
36471
+ display() {
36472
+ this.displayLegacy();
36716
36473
  }
36717
36474
  /**
36718
- * Converts a string to an url.
36475
+ * Legacy way to render the plugin settings tab imperatively.
36719
36476
  *
36720
- * @param str - The string to convert.
36721
- * @returns The url.
36477
+ * The pre-declarative fallback: Obsidian only calls it when {@link getSettingDefinitions} returns an empty
36478
+ * array, i.e. when the consumer has not overridden {@link getSettingDefinitionItems}. Such a consumer
36479
+ * overrides this method and builds the UI with {@link SettingEx} and {@link bind}.
36722
36480
  */
36723
- valueFromString(str) {
36724
- return str;
36481
+ displayLegacy() {
36482
+ this.beginRenderCycle();
36483
+ this.containerEl.empty();
36725
36484
  }
36726
- };
36727
-
36728
- // src/obsidian/setting-components/value-component-with-change-tracking.ts
36729
- var value_component_with_change_tracking_exports = {};
36730
-
36731
- // src/obsidian/setting-components/week-component.ts
36732
- var week_component_exports = {};
36733
- __export(week_component_exports, {
36734
- WeekComponent: () => WeekComponent
36735
- });
36736
- var import_obsidian151 = require("obsidian");
36737
- init_css_class();
36738
- var moment6 = extractDefaultExportInterop(import_obsidian151.moment);
36739
- var DATE_FORMAT3 = "YYYY-[W]WW";
36740
- var WeekComponent = class extends TypedRangeTextComponent {
36741
36485
  /**
36742
- * Creates a new Week component.
36486
+ * Reads the value backing a native `control` setting definition.
36743
36487
  *
36744
- * @param containerEl - The container element of the component.
36488
+ * Obsidian calls it on every render of a `control`-type definition. The inherited implementation reads
36489
+ * `plugin.settings`, which a plugin built on {@link PluginSettingsComponentBase} never populates, so it is
36490
+ * routed to the settings component instead.
36491
+ *
36492
+ * @param key - The settings property name.
36493
+ * @returns The current value.
36745
36494
  */
36746
- constructor(containerEl) {
36747
- super({
36748
- containerEl,
36749
- cssClass: "week-component" /* WeekComponent */,
36750
- type: "week"
36751
- });
36495
+ getControlValue(key) {
36496
+ return this.getPluginSettingsProperty(castTo(key));
36752
36497
  }
36753
36498
  /**
36754
- * Converts a string to a Week.
36499
+ * Returns the declarative setting definitions rendered by Obsidian 1.13+.
36755
36500
  *
36756
- * @param str - The string to convert.
36757
- * @returns The week.
36501
+ * Delegates to {@link getSettingDefinitionItems}. When a consumer has not overridden that hook it returns
36502
+ * an empty array, and Obsidian falls back to the imperative {@link displayLegacy} path.
36503
+ *
36504
+ * @returns The setting definitions.
36758
36505
  */
36759
- valueFromString(str) {
36760
- const parsed = moment6(str, DATE_FORMAT3);
36761
- if (!parsed.isValid()) {
36762
- throw new Error("Invalid week");
36763
- }
36764
- return {
36765
- weekNumber: parsed.isoWeek(),
36766
- year: parsed.year()
36767
- };
36506
+ getSettingDefinitions() {
36507
+ return this.getSettingDefinitionItems();
36768
36508
  }
36769
36509
  /**
36770
- * Converts a week to a string.
36771
- *
36772
- * @param value - The week to convert.
36773
- * @returns The string.
36510
+ * Hides the plugin settings tab.
36774
36511
  */
36775
- valueToString(value) {
36776
- const date = moment6().year(value.year).isoWeek(value.weekNumber);
36777
- return date.format(DATE_FORMAT3);
36512
+ hide() {
36513
+ super.hide();
36514
+ this.saveSettingsDebounced.cancel();
36515
+ this._isOpen = false;
36516
+ this.endRenderCycle();
36517
+ this.component.unload();
36518
+ invokeAsyncSafely(() => this.hideAsync());
36778
36519
  }
36779
- };
36780
-
36781
- // src/obsidian/setting-ex.ts
36782
- var setting_ex_exports = {};
36783
- __export(setting_ex_exports, {
36784
- SettingEx: () => SettingEx
36785
- });
36786
- var import_obsidian152 = require("obsidian");
36787
- var SettingEx = class extends import_obsidian152.Setting {
36788
36520
  /**
36789
- * Adds a {@link CheckboxComponent} to the setting.
36521
+ * Async actions to perform when the settings tab is being hidden.
36790
36522
  *
36791
- * @param cb - The callback to call with the component.
36792
- * @returns The setting instance.
36523
+ * @returns A {@link Promise} that resolves when the settings tab is hidden.
36793
36524
  */
36794
- addCheckbox(cb) {
36795
- return this.addComponentClass(CheckboxComponent, cb);
36525
+ async hideAsync() {
36526
+ await this.pluginSettingsComponent.saveToFile(SAVE_TO_FILE_CONTEXT);
36796
36527
  }
36797
36528
  /**
36798
- * Adds a {@link CodeHighlighterComponent} to the setting.
36529
+ * Re-renders the settings tab after the underlying state changed.
36799
36530
  *
36800
- * @param cb - The callback to call with the component.
36801
- * @returns The setting instance.
36531
+ * Rebuilds the definitions and re-renders, which covers both paths: Obsidian renders the declarative
36532
+ * definitions when {@link getSettingDefinitionItems} provides them, and falls back to
36533
+ * {@link displayLegacy} when it does not. Nothing is rendered while the tab is not the one on screen.
36534
+ *
36535
+ * Use it only for changes that alter the STRUCTURE of the tab — rows added or removed. When only a
36536
+ * {@link PluginSettingsTabBaseSettingExParams.disabled} / {@link PluginSettingsTabBaseSettingExParams.visible}
36537
+ * predicate has to be re-evaluated, call the much cheaper {@link refreshDomState} instead, which toggles the
36538
+ * rendered DOM in place.
36802
36539
  */
36803
- addCodeHighlighter(cb) {
36804
- return this.addComponentClass(CodeHighlighterComponent, cb);
36540
+ refresh() {
36541
+ this.update();
36805
36542
  }
36806
36543
  /**
36807
- * Adds a component to the setting.
36544
+ * Persists the value of a native `control` setting definition.
36808
36545
  *
36809
- * @typeParam T - The type of the component to add.
36810
- * @param componentClass - The class of the component to add.
36811
- * @param cb - The callback to call with the component.
36812
- * @returns The setting instance.
36546
+ * The counterpart of {@link getControlValue}: it routes the write to the settings component instead of the
36547
+ * inherited `plugin.saveData` path, so validation, transformers and the debounced save all apply as they do
36548
+ * for a {@link bind}-ed component.
36549
+ *
36550
+ * @param key - The settings property name.
36551
+ * @param value - The value to persist.
36552
+ * @returns A {@link Promise} that resolves when the value is set.
36813
36553
  */
36814
- addComponentClass(componentClass, cb) {
36815
- return this.addComponent((el) => {
36816
- const component = new componentClass(el);
36817
- cb(component);
36818
- return component;
36819
- });
36554
+ async setControlValue(key, value) {
36555
+ await this.pluginSettingsComponent.setProperty(castTo(key), castTo(value));
36556
+ this.saveSettingsDebounced();
36820
36557
  }
36821
36558
  /**
36822
- * Adds a {@link DateComponent} to the setting.
36823
- *
36824
- * @param cb - The callback to call with the component.
36825
- * @returns The setting instance.
36559
+ * Shows the plugin settings tab.
36826
36560
  */
36827
- addDate(cb) {
36828
- return this.addComponentClass(DateComponent, cb);
36561
+ show() {
36562
+ this.app.setting.openTab(this);
36829
36563
  }
36830
36564
  /**
36831
- * Adds a {@link DateTimeComponent} to the setting.
36565
+ * The declarative setting definitions for the tab (Obsidian 1.13+).
36832
36566
  *
36833
- * @param cb - The callback to call with the component.
36834
- * @returns The setting instance.
36567
+ * Consumers override this, typically building each row with {@link settingEx} and {@link bind} and grouping
36568
+ * them with `settingGroupEx`. Returning an empty array — the default — makes Obsidian fall back to the
36569
+ * imperative {@link displayLegacy} path.
36570
+ *
36571
+ * MUST be a pure builder. Obsidian calls it when the tab is registered (`addSettingTab`), long before the
36572
+ * tab is ever opened, in order to index the settings for search. Anything with a side effect belongs inside
36573
+ * a row's {@link PluginSettingsTabBaseSettingExParams.render} callback, which runs only when the row is
36574
+ * actually rendered.
36575
+ *
36576
+ * @returns The setting definitions.
36835
36577
  */
36836
- addDateTime(cb) {
36837
- return this.addComponentClass(DateTimeComponent, cb);
36578
+ getSettingDefinitionItems() {
36579
+ return [];
36838
36580
  }
36839
36581
  /**
36840
- * Adds an {@link EmailComponent} to the setting.
36582
+ * Called when the plugin settings are loaded.
36841
36583
  *
36842
- * @param cb - The callback to call with the component.
36843
- * @returns The setting instance.
36584
+ * @param _loadedState - The loaded settings state.
36585
+ * @param _isInitialLoad - Whether the settings are being loaded for the first time.
36586
+ * @returns A {@link Promise} that resolves when the settings are loaded.
36844
36587
  */
36845
- addEmail(cb) {
36846
- return this.addComponentClass(EmailComponent, cb);
36588
+ async onLoadSettings(_loadedState, _isInitialLoad) {
36589
+ this.refresh();
36590
+ await noopAsync();
36847
36591
  }
36848
36592
  /**
36849
- * Adds a {@link FileComponent} to the setting.
36593
+ * Revalidates the settings.
36850
36594
  *
36851
- * @param cb - The callback to call with the component.
36852
- * @returns The setting instance.
36595
+ * @returns A {@link Promise} that resolves when the settings are revalidated.
36853
36596
  */
36854
- addFile(cb) {
36855
- return this.addComponentClass(FileComponent, cb);
36597
+ async revalidate() {
36598
+ const validationMessages = await this.pluginSettingsComponent.revalidate();
36599
+ await this.updateValidations(validationMessages);
36856
36600
  }
36857
36601
  /**
36858
- * Adds a {@link MonthComponent} to the setting.
36602
+ * Builds a search-indexable declarative row that is rendered imperatively.
36859
36603
  *
36860
- * @param cb - The callback to call with the component.
36861
- * @returns The setting instance.
36604
+ * The bridge between the declarative API and ODU's imperative building blocks: Obsidian owns the row (so it
36605
+ * indexes it for search and evaluates its {@link PluginSettingsTabBaseSettingExParams.visible} /
36606
+ * {@link PluginSettingsTabBaseSettingExParams.disabled} predicates on every
36607
+ * {@link refreshDomState}), while {@link PluginSettingsTabBaseSettingExParams.render} fills it in with
36608
+ * {@link SettingEx} adders and {@link bind} exactly as an imperative tab would.
36609
+ *
36610
+ * @param params - The row params.
36611
+ * @returns The setting definition.
36862
36612
  */
36863
- addMonth(cb) {
36864
- return this.addComponentClass(MonthComponent, cb);
36613
+ settingEx(params) {
36614
+ return normalizeOptionalProperties({
36615
+ aliases: params.aliases,
36616
+ desc: params.desc,
36617
+ disabled: params.disabled,
36618
+ name: params.name,
36619
+ render: (setting, group) => this.renderSettingEx({ group, setting, settingExParams: params }),
36620
+ searchable: params.searchable,
36621
+ visible: params.visible
36622
+ });
36865
36623
  }
36866
36624
  /**
36867
- * Adds a {@link MultipleDropdownComponent} to the setting.
36625
+ * Builds a declarative heading group.
36868
36626
  *
36869
- * @param cb - The callback to call with the component.
36870
- * @returns The setting instance.
36627
+ * The declarative counterpart of `SettingGroupEx`: where that class appends a group to a container
36628
+ * imperatively, this returns the definition Obsidian renders, so a group-structured tab keeps its shape
36629
+ * after the migration.
36630
+ *
36631
+ * @param params - The group params.
36632
+ * @returns The group definition.
36871
36633
  */
36872
- addMultipleDropdown(cb) {
36873
- return this.addComponentClass(MultipleDropdownComponent, cb);
36634
+ settingGroupEx(params) {
36635
+ return normalizeOptionalProperties({
36636
+ ...params,
36637
+ type: "group"
36638
+ });
36639
+ }
36640
+ beginRenderCycle() {
36641
+ this.endRenderCycle();
36642
+ this.currentRenderComponent = this.createRenderComponent();
36643
+ }
36644
+ createRenderComponent() {
36645
+ this._isOpen = true;
36646
+ this.component.load();
36647
+ return this.component.addChild(new ComponentEx());
36648
+ }
36649
+ endRenderCycle() {
36650
+ const renderComponent = this.currentRenderComponent;
36651
+ if (!renderComponent) {
36652
+ return;
36653
+ }
36654
+ this.currentRenderComponent = null;
36655
+ this.component.removeChild(renderComponent);
36656
+ }
36657
+ getPluginSettingsProperty(propertyName) {
36658
+ const settings = this.pluginSettings;
36659
+ return settings[propertyName];
36660
+ }
36661
+ getRenderComponent() {
36662
+ this.currentRenderComponent ??= this.createRenderComponent();
36663
+ return this.currentRenderComponent;
36664
+ }
36665
+ async onSaveSettings(params) {
36666
+ const {
36667
+ context,
36668
+ newState,
36669
+ oldState: _oldState
36670
+ } = params;
36671
+ if (context === SAVE_TO_FILE_CONTEXT) {
36672
+ await this.updateValidations(newState.validationMessages);
36673
+ return;
36674
+ }
36675
+ this.refresh();
36874
36676
  }
36677
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type -- Mirrors Obsidian's `SettingDefinitionRender.render`, whose cleanup function is optional.
36678
+ renderSettingEx(params) {
36679
+ const rowComponent = this.createRenderComponent();
36680
+ const previousRenderComponent = this.currentRenderComponent;
36681
+ this.currentRenderComponent = rowComponent;
36682
+ try {
36683
+ const cleanup = params.settingExParams.render(adoptSettingEx(params.setting), params.group);
36684
+ return () => {
36685
+ if (typeof cleanup === "function") {
36686
+ cleanup();
36687
+ }
36688
+ this.component.removeChild(rowComponent);
36689
+ };
36690
+ } finally {
36691
+ this.currentRenderComponent = previousRenderComponent;
36692
+ }
36693
+ }
36694
+ async updateValidations(validationMessages) {
36695
+ for (const [propertyName, validationMessage] of Object.entries(validationMessages)) {
36696
+ await this.triggerAsync("validationMessageChanged", propertyName, validationMessage);
36697
+ }
36698
+ }
36699
+ };
36700
+
36701
+ // src/obsidian/plugin/plugin.ts
36702
+ var plugin_exports = {};
36703
+ __export(plugin_exports, {
36704
+ PluginBase: () => PluginBase,
36705
+ reloadPlugin: () => reloadPlugin,
36706
+ showErrorAndDisablePlugin: () => showErrorAndDisablePlugin
36707
+ });
36708
+ var import_obsidian147 = require("obsidian");
36709
+ init_async_events();
36710
+ init_error();
36711
+ init_function();
36712
+ init_type_guards();
36713
+ var PluginBase = class extends mixinAsyncEvents()(import_obsidian147.Plugin) {
36875
36714
  /**
36876
- * Adds a {@link MultipleEmailComponent} to the setting.
36715
+ * Gets abort signal component.
36877
36716
  *
36878
- * @param cb - The callback to call with the component.
36879
- * @returns The setting instance.
36717
+ * @returns abort signal component.
36880
36718
  */
36881
- addMultipleEmail(cb) {
36882
- return this.addComponentClass(MultipleEmailComponent, cb);
36719
+ get abortSignalComponent() {
36720
+ return ensureNonNullable(this._abortSignalComponent);
36883
36721
  }
36884
36722
  /**
36885
- * Adds a {@link MultipleFileComponent} to the setting.
36723
+ * Sets abort signal component.
36886
36724
  *
36887
- * @param cb - The callback to call with the component.
36888
- * @returns The setting instance.
36725
+ * @param value - Abort signal component.
36889
36726
  */
36890
- addMultipleFile(cb) {
36891
- return this.addComponentClass(MultipleFileComponent, cb);
36727
+ set abortSignalComponent(value) {
36728
+ this._abortSignalComponent = value;
36892
36729
  }
36893
36730
  /**
36894
- * Adds a {@link MultipleTextComponent} to the setting.
36731
+ * Gets async error handler component.
36895
36732
  *
36896
- * @param cb - The callback to call with the component.
36897
- * @returns The setting instance.
36733
+ * @returns async error handler component.
36898
36734
  */
36899
- addMultipleText(cb) {
36900
- return this.addComponentClass(MultipleTextComponent, cb);
36735
+ get asyncErrorHandlerComponent() {
36736
+ return ensureNonNullable(this._asyncErrorHandlerComponent);
36901
36737
  }
36902
36738
  /**
36903
- * Adds a {@link NumberComponent} to the setting.
36739
+ * Sets async error handler component.
36904
36740
  *
36905
- * @param cb - The callback to call with the component.
36906
- * @returns The setting instance.
36741
+ * @param value - Async error handler component.
36907
36742
  */
36908
- addNumber(cb) {
36909
- return this.addComponentClass(NumberComponent, cb);
36743
+ set asyncErrorHandlerComponent(value) {
36744
+ this._asyncErrorHandlerComponent = value;
36910
36745
  }
36911
36746
  /**
36912
- * Adds a {@link PasswordComponent} to the setting.
36747
+ * Gets the shared command handler component. Register a plugin's commands on it via
36748
+ * {@link CommandHandlerComponent.registerCommandHandlers} rather than constructing your own
36749
+ * {@link CommandHandlerComponent} — the app-backed active-file provider, command registrar, menu
36750
+ * event registrar, and plugin name are already wired.
36913
36751
  *
36914
- * @param cb - The callback to call with the component.
36915
- * @returns The setting instance.
36752
+ * @returns The command handler component.
36916
36753
  */
36917
- addPassword(cb) {
36918
- return this.addComponentClass(PasswordComponent, cb);
36754
+ get commandHandlerComponent() {
36755
+ return ensureNonNullable(this._commandHandlerComponent);
36919
36756
  }
36920
36757
  /**
36921
- * Adds a {@link TelephoneComponent} to the setting.
36758
+ * Sets the command handler component.
36922
36759
  *
36923
- * @param cb - The callback to call with the component.
36924
- * @returns The setting instance.
36760
+ * @param value - The command handler component.
36925
36761
  */
36926
- addTelephone(cb) {
36927
- return this.addComponentClass(TelephoneComponent, cb);
36762
+ set commandHandlerComponent(value) {
36763
+ this._commandHandlerComponent = value;
36928
36764
  }
36929
36765
  /**
36930
- * Adds a {@link TimeComponent} to the setting.
36766
+ * Gets console debug component.
36931
36767
  *
36932
- * @param cb - The callback to call with the component.
36933
- * @returns The setting instance.
36768
+ * @returns console debug component.
36934
36769
  */
36935
- addTime(cb) {
36936
- return this.addComponentClass(TimeComponent, cb);
36770
+ get consoleDebugComponent() {
36771
+ return ensureNonNullable(this._consoleDebugComponent);
36937
36772
  }
36938
36773
  /**
36939
- * Adds a {@link TriStateCheckboxComponent} to the setting.
36774
+ * Sets console debug component.
36940
36775
  *
36941
- * @param cb - The callback to call with the component.
36942
- * @returns The setting instance.
36776
+ * @param value - Console debug component.
36943
36777
  */
36944
- addTriStateCheckbox(cb) {
36945
- return this.addComponentClass(TriStateCheckboxComponent, cb);
36778
+ set consoleDebugComponent(value) {
36779
+ this._consoleDebugComponent = value;
36946
36780
  }
36947
36781
  /**
36948
- * Adds a {@link TypedDropdownComponent} to the setting.
36782
+ * Gets plugin context component (plugin ID, debug controller, library styles).
36949
36783
  *
36950
- * @typeParam T - The type of the dropdown items.
36951
- * @param cb - The callback to call with the component.
36952
- * @returns The setting instance.
36784
+ * @returns plugin context component.
36953
36785
  */
36954
- addTypedDropdown(cb) {
36955
- return this.addComponentClass(TypedDropdownComponent, cb);
36786
+ get pluginContextComponent() {
36787
+ return ensureNonNullable(this._pluginContextComponent);
36956
36788
  }
36957
36789
  /**
36958
- * Adds a {@link TypedMultipleDropdownComponent} to the setting.
36790
+ * Sets plugin context component.
36959
36791
  *
36960
- * @typeParam T - The type of the items in the dropdown.
36961
- * @param cb - The callback to call with the component.
36962
- * @returns The setting instance.
36792
+ * @param value - Plugin context component.
36963
36793
  */
36964
- addTypedMultipleDropdown(cb) {
36965
- return this.addComponentClass(TypedMultipleDropdownComponent, cb);
36794
+ set pluginContextComponent(value) {
36795
+ this._pluginContextComponent = value;
36966
36796
  }
36967
36797
  /**
36968
- * Adds an {@link UrlComponent} to the setting.
36798
+ * Gets plugin notice component.
36969
36799
  *
36970
- * @param cb - The callback to call with the component.
36971
- * @returns The setting instance.
36800
+ * @returns plugin notice component.
36972
36801
  */
36973
- addUrl(cb) {
36974
- return this.addComponentClass(UrlComponent, cb);
36802
+ get pluginNoticeComponent() {
36803
+ return ensureNonNullable(this._pluginNoticeComponent);
36975
36804
  }
36976
36805
  /**
36977
- * Adds a {@link WeekComponent} to the setting.
36806
+ * Sets plugin notice component.
36978
36807
  *
36979
- * @param cb - The callback to call with the component.
36980
- * @returns The setting instance.
36808
+ * @param value - Plugin notice component.
36981
36809
  */
36982
- addWeek(cb) {
36983
- return this.addComponentClass(WeekComponent, cb);
36810
+ set pluginNoticeComponent(value) {
36811
+ this._pluginNoticeComponent = value;
36984
36812
  }
36985
- };
36813
+ /**
36814
+ * Gets the editor lock component, used to lock notes read-only during long operations. Owned by
36815
+ * the plugin, so its locks are released automatically when the plugin unloads.
36816
+ *
36817
+ * @returns Editor lock component.
36818
+ */
36819
+ get resourceLockComponent() {
36820
+ return ensureNonNullable(this._resourceLockComponent);
36821
+ }
36822
+ /**
36823
+ * Sets the editor lock component.
36824
+ *
36825
+ * @param value - Editor lock component.
36826
+ */
36827
+ set resourceLockComponent(value) {
36828
+ this._resourceLockComponent = value;
36829
+ }
36830
+ _abortSignalComponent;
36831
+ _asyncErrorHandlerComponent;
36832
+ _commandHandlerComponent;
36833
+ _consoleDebugComponent;
36834
+ _pluginContextComponent;
36835
+ _pluginNoticeComponent;
36836
+ _resourceLockComponent;
36837
+ wrapperComponent = new ComponentEx();
36838
+ /**
36839
+ * Adds a child component.
36840
+ *
36841
+ * The child is added to an internal wrapper component so that, during {@link onloadImpl},
36842
+ * children are queued and then loaded sequentially (children-first) when the plugin loads.
36843
+ *
36844
+ * @typeParam TComponent - The type of component to add.
36845
+ * @param component - The component instance to add.
36846
+ * @returns The added component.
36847
+ */
36848
+ addChild(component) {
36849
+ return this.wrapperComponent.addChild(component);
36850
+ }
36851
+ /**
36852
+ * Called when the external settings change.
36853
+ *
36854
+ * Override in subclass if needed. Make sure to call `await super.onExternalSettingsChange()` first.
36855
+ */
36856
+ async onExternalSettingsChange() {
36857
+ await super.onExternalSettingsChange?.();
36858
+ await this.triggerAsync("externalSettingsChange");
36859
+ }
36860
+ /**
36861
+ * Called when the plugin is loaded.
36862
+ *
36863
+ * Orchestrates loading: registers the universal components, lets the subclass wire its own
36864
+ * components via {@link onloadImpl}, then loads all of them sequentially (children-first).
36865
+ *
36866
+ * Do NOT override this method. Override {@link onloadImpl} instead.
36867
+ */
36868
+ async onload() {
36869
+ try {
36870
+ await initI18N(this.createTranslationsMap());
36871
+ this.pluginContextComponent = this.addChild(
36872
+ new PluginContextComponent({
36873
+ app: this.app,
36874
+ pluginId: this.manifest.id
36875
+ })
36876
+ );
36877
+ this.pluginNoticeComponent = this.addChild(
36878
+ new PluginNoticeComponent({
36879
+ app: this.app,
36880
+ pluginName: this.manifest.name
36881
+ })
36882
+ );
36883
+ this.asyncErrorHandlerComponent = this.addChild(new AsyncErrorHandlerComponent(this.pluginNoticeComponent));
36884
+ this.abortSignalComponent = this.addChild(new AbortSignalComponent(this.manifest.id));
36885
+ this.consoleDebugComponent = this.addChild(new ConsoleDebugComponent(this.manifest.id));
36886
+ this.resourceLockComponent = this.addChild(new ResourceLockComponent(this.app, this.manifest.id));
36887
+ this.commandHandlerComponent = this.addChild(
36888
+ new CommandHandlerComponent({
36889
+ activeFileProvider: new AppActiveFileProvider(this.app),
36890
+ commandRegistrar: new PluginCommandRegistrar(this),
36891
+ menuEventRegistrar: this.addChild(new MenuEventRegistrarComponent(this.app)),
36892
+ pluginName: this.manifest.name
36893
+ })
36894
+ );
36895
+ this.commandHandlerComponent.registerCommandHandlers([
36896
+ new UnlockActiveNoteCommandHandler({
36897
+ app: this.app,
36898
+ resourceLockComponent: this.resourceLockComponent
36899
+ })
36900
+ ]);
36901
+ await this.onloadImpl();
36902
+ super.addChild(this.wrapperComponent);
36903
+ await this.wrapperComponent.loadWithPromises();
36904
+ } catch (error) {
36905
+ printError(new Error(`Error loading plugin ${this.manifest.name} (${this.manifest.id})`, { cause: error }));
36906
+ throw error;
36907
+ }
36908
+ }
36909
+ /**
36910
+ * Removes a child component.
36911
+ *
36912
+ * @typeParam TComponent - The type of component to remove.
36913
+ * @param component - The component instance to remove.
36914
+ * @returns The removed component.
36915
+ */
36916
+ removeChild(component) {
36917
+ return this.wrapperComponent.removeChild(component);
36918
+ }
36919
+ /**
36920
+ * Provides the translations map used to initialize i18n during {@link onload}.
36921
+ *
36922
+ * Override in subclass to supply plugin-specific translations. The default returns the built-in
36923
+ * `obsidian-dev-utils` translations.
36924
+ *
36925
+ * @returns The translations map.
36926
+ */
36927
+ createTranslationsMap() {
36928
+ return defaultTranslationsMap;
36929
+ }
36930
+ /**
36931
+ * Called during {@link onload} to wire plugin-specific child components.
36932
+ *
36933
+ * Override in subclass to add child components via {@link addChild}. The universal components are
36934
+ * available here. Children are loaded sequentially in the order they are added (children-first).
36935
+ *
36936
+ * @returns A {@link Promise} that resolves when the subclass load logic is complete.
36937
+ */
36938
+ onloadImpl() {
36939
+ return noopAsync();
36940
+ }
36941
+ };
36942
+ async function reloadPlugin(plugin) {
36943
+ const plugins = plugin.app.plugins;
36944
+ const pluginId = plugin.manifest.id;
36945
+ await plugins.disablePlugin(pluginId);
36946
+ await plugins.enablePlugin(pluginId);
36947
+ }
36948
+ async function showErrorAndDisablePlugin(plugin, message) {
36949
+ const pluginNoticeComponent = new PluginNoticeComponent({
36950
+ app: plugin.app,
36951
+ pluginName: plugin.manifest.name
36952
+ });
36953
+ pluginNoticeComponent.showNotice(message);
36954
+ printError(new Error(message));
36955
+ await plugin.app.plugins.disablePlugin(plugin.manifest.id);
36956
+ }
36957
+
36958
+ // src/obsidian/plugin-cli-handler-registrar.ts
36959
+ var plugin_cli_handler_registrar_exports = {};
36960
+ __export(plugin_cli_handler_registrar_exports, {
36961
+ PluginCliHandlerRegistrar: () => PluginCliHandlerRegistrar
36962
+ });
36963
+ var import_obsidian148 = require("obsidian");
36964
+ var PluginCliHandlerRegistrar = class {
36965
+ /**
36966
+ * Creates a new instance of the {@link PluginCliHandlerRegistrar} class.
36967
+ *
36968
+ * @param plugin - The Obsidian plugin instance.
36969
+ */
36970
+ constructor(plugin) {
36971
+ this.plugin = plugin;
36972
+ }
36973
+ plugin;
36974
+ /**
36975
+ * Registers a CLI handler.
36976
+ *
36977
+ * @param params - The parameters for the CLI handler registration.
36978
+ */
36979
+ registerCliHandler(params) {
36980
+ this.plugin.registerCliHandler(params.command, params.description, params.flags, (cliData) => normalizePromisable(params.handler(cliData)));
36981
+ }
36982
+ };
36983
+
36984
+ // src/obsidian/popovers/index.ts
36985
+ var popovers_exports = {};
36986
+ __export(popovers_exports, {
36987
+ "field-popover": () => field_popover_exports,
36988
+ popover: () => popover_exports,
36989
+ "popover-anchor": () => popover_anchor_exports
36990
+ });
36991
+
36992
+ // src/obsidian/popovers/field-popover.ts
36993
+ var field_popover_exports = {};
36994
+ __export(field_popover_exports, {
36995
+ editFieldsInPopover: () => editFieldsInPopover
36996
+ });
36997
+ var import_obsidian150 = require("obsidian");
36998
+ init_css_class();
36999
+
37000
+ // src/obsidian/popovers/popover.ts
37001
+ var popover_exports = {};
37002
+ __export(popover_exports, {
37003
+ showPopover: () => showPopover
37004
+ });
37005
+ var import_obsidian149 = require("obsidian");
37006
+ init_css_class();
37007
+ init_plugin_context();
37008
+ var ANCHOR_GAP_IN_PIXELS = 4;
37009
+ var VIEWPORT_MARGIN_IN_PIXELS = 8;
37010
+ async function showPopover(params) {
37011
+ const {
37012
+ anchor,
37013
+ build,
37014
+ cancelButtonText,
37015
+ cssClasses,
37016
+ okButtonText
37017
+ } = params;
37018
+ const doc = anchor.doc;
37019
+ const win = getDocumentWindow(doc);
37020
+ const popoverEl = doc.body.createDiv({ cls: "menu" });
37021
+ addPluginCssClasses(popoverEl, ["popover" /* Popover */, ...cssClasses ?? []]);
37022
+ return await new Promise((resolve2) => {
37023
+ const state = { isClosed: false };
37024
+ function close(result) {
37025
+ if (state.isClosed) {
37026
+ return;
37027
+ }
37028
+ state.isClosed = true;
37029
+ doc.removeEventListener("pointerdown", handlePointerDown, true);
37030
+ popoverEl.remove();
37031
+ resolve2(result);
37032
+ }
37033
+ function handleCancel() {
37034
+ close(null);
37035
+ }
37036
+ function handleOk() {
37037
+ close(getValue());
37038
+ }
37039
+ function handlePointerDown(evt) {
37040
+ if (evt.composedPath().includes(popoverEl)) {
37041
+ return;
37042
+ }
37043
+ close(null);
37044
+ }
37045
+ const getValue = build({
37046
+ cancel: handleCancel,
37047
+ confirm: handleOk,
37048
+ contentEl: popoverEl
37049
+ });
37050
+ popoverEl.addEventListener("keydown", (evt) => {
37051
+ if (evt.key === "Enter") {
37052
+ evt.preventDefault();
37053
+ handleOk();
37054
+ return;
37055
+ }
37056
+ if (evt.key === "Escape") {
37057
+ evt.preventDefault();
37058
+ handleCancel();
37059
+ }
37060
+ });
37061
+ const buttonsSetting = new import_obsidian149.Setting(popoverEl);
37062
+ buttonsSetting.addButton((button) => {
37063
+ button.setButtonText(okButtonText ?? t2(($) => $.obsidianDevUtils.buttons.ok)).setCta().setClass("ok-button" /* OkButton */).onClick(handleOk);
37064
+ });
37065
+ buttonsSetting.addButton((button) => {
37066
+ button.setButtonText(cancelButtonText ?? t2(($) => $.obsidianDevUtils.buttons.cancel)).setClass("cancel-button" /* CancelButton */).onClick(handleCancel);
37067
+ });
37068
+ doc.addEventListener("pointerdown", handlePointerDown, true);
37069
+ positionAtAnchor(popoverEl, anchor, win);
37070
+ focusFirstInput(popoverEl);
37071
+ });
37072
+ }
37073
+ function focusFirstInput(popoverEl) {
37074
+ const inputEl = popoverEl.querySelector("input");
37075
+ if (!inputEl) {
37076
+ return;
37077
+ }
37078
+ inputEl.focus();
37079
+ inputEl.select();
37080
+ }
37081
+ function positionAtAnchor(popoverEl, anchor, win) {
37082
+ const maxLeft = Math.max(VIEWPORT_MARGIN_IN_PIXELS, win.innerWidth - popoverEl.offsetWidth - VIEWPORT_MARGIN_IN_PIXELS);
37083
+ const maxTop = Math.max(VIEWPORT_MARGIN_IN_PIXELS, win.innerHeight - popoverEl.offsetHeight - VIEWPORT_MARGIN_IN_PIXELS);
37084
+ const left = Math.min(Math.max(anchor.left, VIEWPORT_MARGIN_IN_PIXELS), maxLeft);
37085
+ const top = Math.min(Math.max(anchor.bottom + ANCHOR_GAP_IN_PIXELS, VIEWPORT_MARGIN_IN_PIXELS), maxTop);
37086
+ popoverEl.style.left = `${String(Math.round(left + win.scrollX))}px`;
37087
+ popoverEl.style.top = `${String(Math.round(top + win.scrollY))}px`;
37088
+ }
37089
+
37090
+ // src/obsidian/popovers/field-popover.ts
37091
+ async function editFieldsInPopover(params) {
37092
+ const {
37093
+ anchor,
37094
+ cancelButtonText,
37095
+ cssClasses,
37096
+ fields,
37097
+ okButtonText
37098
+ } = params;
37099
+ return await showPopover(normalizeOptionalProperties({
37100
+ anchor,
37101
+ build({ contentEl }) {
37102
+ const editors = fields.map((field) => ({
37103
+ key: field.key,
37104
+ textComponent: addField(contentEl, field)
37105
+ }));
37106
+ return () => {
37107
+ const values = {};
37108
+ for (const editor of editors) {
37109
+ values[editor.key] = editor.textComponent.getValue();
37110
+ }
37111
+ return values;
37112
+ };
37113
+ },
37114
+ cancelButtonText,
37115
+ cssClasses,
37116
+ okButtonText
37117
+ }));
37118
+ }
37119
+ function addField(containerEl, field) {
37120
+ const setting = new import_obsidian150.Setting(containerEl).setName(field.name);
37121
+ const textComponent = new import_obsidian150.TextComponent(setting.controlEl);
37122
+ textComponent.setValue(field.defaultValue ?? "");
37123
+ textComponent.setPlaceholder(field.placeholder ?? "");
37124
+ textComponent.inputEl.addClass("text-box" /* TextBox */);
37125
+ return textComponent;
37126
+ }
37127
+
37128
+ // src/obsidian/react/index.ts
37129
+ var react_exports = {};
37130
+ __export(react_exports, {
37131
+ "app-context": () => app_context_exports
37132
+ });
37133
+
37134
+ // src/obsidian/react/app-context.ts
37135
+ var app_context_exports = {};
37136
+ __export(app_context_exports, {
37137
+ AppContext: () => AppContext,
37138
+ useApp: () => useApp
37139
+ });
37140
+ var import_obsidian151 = require("obsidian");
37141
+ var import_react = __toESM(require_react(), 1);
37142
+ init_type_guards();
37143
+ var AppContext = (0, import_react.createContext)(void 0);
37144
+ function useApp() {
37145
+ return ensureNonNullable((0, import_react.useContext)(AppContext), "AppContext not found");
37146
+ }
37147
+
37148
+ // src/obsidian/ribbon-icon-registrar.ts
37149
+ var ribbon_icon_registrar_exports = {};
37150
+ __export(ribbon_icon_registrar_exports, {
37151
+ PluginRibbonIconRegistrar: () => PluginRibbonIconRegistrar
37152
+ });
37153
+ var import_obsidian152 = require("obsidian");
37154
+ var PluginRibbonIconRegistrar = class {
37155
+ /**
37156
+ * Creates a new instance of the {@link PluginRibbonIconRegistrar} class.
37157
+ *
37158
+ * @param plugin - The Obsidian plugin instance.
37159
+ */
37160
+ constructor(plugin) {
37161
+ this.plugin = plugin;
37162
+ }
37163
+ plugin;
37164
+ /**
37165
+ * Registers a ribbon icon.
37166
+ *
37167
+ * @param params - The parameters for the ribbon icon registration.
37168
+ * @returns The HTML element representing the registered ribbon icon.
37169
+ */
37170
+ addRibbonIcon(params) {
37171
+ return this.plugin.addRibbonIcon(params.icon, params.title, params.callback);
37172
+ }
37173
+ };
37174
+
37175
+ // src/obsidian/setting-components/index.ts
37176
+ var setting_components_exports = {};
37177
+ __export(setting_components_exports, {
37178
+ "checkbox-component": () => checkbox_component_exports,
37179
+ "code-highlighter-component": () => code_highlighter_component_exports,
37180
+ "date-component": () => date_component_exports,
37181
+ "date-time-component": () => date_time_component_exports,
37182
+ "email-component": () => email_component_exports,
37183
+ "file-component": () => file_component_exports,
37184
+ "month-component": () => month_component_exports,
37185
+ "multiple-dropdown-component": () => multiple_dropdown_component_exports,
37186
+ "multiple-email-component": () => multiple_email_component_exports,
37187
+ "multiple-file-component": () => multiple_file_component_exports,
37188
+ "multiple-text-component": () => multiple_text_component_exports,
37189
+ "number-component": () => number_component_exports,
37190
+ "password-component": () => password_component_exports,
37191
+ "setting-component-wrapper": () => setting_component_wrapper_exports,
37192
+ "telephone-component": () => telephone_component_exports,
37193
+ "text-based-component": () => text_based_component_exports,
37194
+ "time-component": () => time_component_exports,
37195
+ "tri-state-checkbox-component": () => tri_state_checkbox_component_exports,
37196
+ "typed-dropdown-component": () => typed_dropdown_component_exports,
37197
+ "typed-multiple-dropdown-component": () => typed_multiple_dropdown_component_exports,
37198
+ "typed-range-text-component": () => typed_range_text_component_exports,
37199
+ "typed-text-component": () => typed_text_component_exports,
37200
+ "url-component": () => url_component_exports,
37201
+ "validator-component": () => validator_component_exports,
37202
+ "value-component-with-change-tracking": () => value_component_with_change_tracking_exports,
37203
+ "week-component": () => week_component_exports
37204
+ });
37205
+
37206
+ // src/obsidian/setting-components/value-component-with-change-tracking.ts
37207
+ var value_component_with_change_tracking_exports = {};
36986
37208
 
36987
37209
  // src/obsidian/setting-group-ex.ts
36988
37210
  var setting_group_ex_exports = {};
@@ -37601,6 +37823,7 @@ __export(merged_exports, {
37601
37823
  addPluginCssClasses: () => addPluginCssClasses,
37602
37824
  addToQueue: () => addToQueue,
37603
37825
  addToQueueAndWait: () => addToQueueAndWait,
37826
+ adoptSettingEx: () => adoptSettingEx,
37604
37827
  alert: () => alert,
37605
37828
  appendCodeBlock: () => appendCodeBlock,
37606
37829
  applyContentChanges: () => applyContentChanges,