@aparte/plugin-model-selector 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -1
- package/dist/angular.d.ts +28 -0
- package/dist/angular.d.ts.map +1 -0
- package/dist/angular.js +27 -0
- package/dist/aparte-model-selector.d.ts +20 -10
- package/dist/aparte-model-selector.d.ts.map +1 -1
- package/dist/custom-elements.json +651 -0
- package/dist/generated/element-attributes.d.ts +23 -0
- package/dist/generated/element-attributes.d.ts.map +1 -0
- package/dist/generated/element.directives.d.ts +58 -0
- package/dist/generated/element.directives.d.ts.map +1 -0
- package/dist/generated/element.directives.js +83 -0
- package/dist/index.js.map +1 -1
- package/dist/react.d.ts +52 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +2 -0
- package/dist/react.js.map +1 -0
- package/dist/svelte.d.ts +30 -0
- package/dist/svelte.d.ts.map +1 -0
- package/dist/svelte.js +2 -0
- package/dist/svelte.js.map +1 -0
- package/dist/vue.d.ts +27 -0
- package/dist/vue.d.ts.map +1 -0
- package/dist/vue.js +2 -0
- package/dist/vue.js.map +1 -0
- package/package.json +54 -5
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A typed Angular surface for every element this package defines.
|
|
3
|
+
*
|
|
4
|
+
* Generated, and that is the point: a hand-written directive is a parallel structure over
|
|
5
|
+
* the manifest with nothing watching it, so an attribute added to an element would be
|
|
6
|
+
* typed in React, Vue and Svelte — which derive from the registry — and silently missing
|
|
7
|
+
* here. That happened, which is why this file is generated now.
|
|
8
|
+
*
|
|
9
|
+
* Outputs emit the event's DETAIL, not the `CustomEvent`, because
|
|
10
|
+
* `(selectChange)="pick($event.value)"` is the Angular idiom. Reach the event itself with
|
|
11
|
+
* a plain host listener when you need `stopPropagation`.
|
|
12
|
+
*/
|
|
13
|
+
import { ElementRef, EventEmitter } from '@angular/core';
|
|
14
|
+
import type { AparteModelChangeEventDetail } from '@aparte/core';
|
|
15
|
+
import * as i0 from "@angular/core";
|
|
16
|
+
/**
|
|
17
|
+
* Writes one declared attribute onto the host element.
|
|
18
|
+
*
|
|
19
|
+
* `applyElementProps` is core's own rule, reused rather than reimplemented: a primitive
|
|
20
|
+
* goes through `setAttribute`, `true` becomes the empty presence attribute,
|
|
21
|
+
* `false`/`null`/`undefined` remove it, and only a value an attribute cannot carry is
|
|
22
|
+
* handed over as a property.
|
|
23
|
+
*/
|
|
24
|
+
declare abstract class AparteElementBase {
|
|
25
|
+
protected readonly host: ElementRef<any>;
|
|
26
|
+
protected write(name: string, value: unknown): void;
|
|
27
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AparteElementBase, never>;
|
|
28
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteElementBase, never, never, {}, {}, never, never, true, never>;
|
|
29
|
+
}
|
|
30
|
+
/** `<aparte-model-selector>` — Selects an AI provider and a model. Renders an `<aparte-select>` with providers grouped into `<aparte-optgroup>`s — a single provider renders a flat list — which is what makes the BYOK pattern possible without core knowing about any vendor. */
|
|
31
|
+
export declare class AparteModelSelectorDirective extends AparteElementBase {
|
|
32
|
+
/** Writes the selection back through the config, so it survives a reload. */
|
|
33
|
+
set persist(v: boolean);
|
|
34
|
+
/** Selects the first model as soon as one is available. */
|
|
35
|
+
set autoSelect(v: boolean);
|
|
36
|
+
/** Adds the dropdown's filter field. */
|
|
37
|
+
set searchable(v: boolean);
|
|
38
|
+
/** Overrides the text shown while nothing is selected. */
|
|
39
|
+
set placeholder(v: string | undefined);
|
|
40
|
+
/** The provider or the model changed; carries both ids. */
|
|
41
|
+
readonly modelChange: EventEmitter<AparteModelChangeEventDetail>;
|
|
42
|
+
protected onModelChange(e: CustomEvent<AparteModelChangeEventDetail>): void;
|
|
43
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AparteModelSelectorDirective, never>;
|
|
44
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AparteModelSelectorDirective, "aparte-model-selector", never, { "persist": { "alias": "persist"; "required": false; }; "autoSelect": { "alias": "autoSelect"; "required": false; }; "searchable": { "alias": "searchable"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; }, { "modelChange": "modelChange"; }, never, never, true, never>;
|
|
45
|
+
static ngAcceptInputType_persist: unknown;
|
|
46
|
+
static ngAcceptInputType_autoSelect: unknown;
|
|
47
|
+
static ngAcceptInputType_searchable: unknown;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Every element directive, for one import in a standalone component.
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* @Component({ imports: [...APARTE_ELEMENT_DIRECTIVES], template: `…` })
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare const APARTE_ELEMENT_DIRECTIVES: readonly [typeof AparteModelSelectorDirective];
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=element.directives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.directives.d.ts","sourceRoot":"","sources":["../../src/generated/element.directives.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AACH,OAAO,EAEH,UAAU,EACV,YAAY,EAMf,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EACR,4BAA4B,EAC/B,MAAM,cAAc,CAAC;;AAEtB;;;;;;;GAOG;AACH,uBACe,iBAAiB;IAC5B,SAAS,CAAC,QAAQ,CAAC,IAAI,kBAAmC;IAE1D,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;yCAHxC,iBAAiB;2CAAjB,iBAAiB;CAM/B;AAED,mRAAmR;AACnR,qBACa,4BAA6B,SAAQ,iBAAiB;IAC/D,6EAA6E;IAC7E,IAA4C,OAAO,CAAC,CAAC,EAAE,OAAO,EAA+B;IAC7F,2DAA2D;IAC3D,IAA4C,UAAU,CAAC,CAAC,EAAE,OAAO,EAAmC;IACpG,wCAAwC;IACxC,IAA4C,UAAU,CAAC,CAAC,EAAE,OAAO,EAAkC;IACnG,0DAA0D;IAC1D,IAAa,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,EAAmC;IAEjF,2DAA2D;IACjD,QAAQ,CAAC,WAAW,6CAAoD;IAGlF,SAAS,CAAC,aAAa,CAAC,CAAC,EAAE,WAAW,CAAC,4BAA4B,CAAC,GAAG,IAAI;yCAdlE,4BAA4B;2CAA5B,4BAA4B;sCA2B4p8c,OAAQ;yCAAR,OAAQ;yCAAR,OAAQ;CAZ5s8c;AAED;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,gDAE5B,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/gen-element-bindings.mjs from this package's
|
|
2
|
+
// custom-elements.json. Do not edit: it is gitignored and rewritten every build.
|
|
3
|
+
// The source of every fact below is the element's own JSDoc.
|
|
4
|
+
/**
|
|
5
|
+
* A typed Angular surface for every element this package defines.
|
|
6
|
+
*
|
|
7
|
+
* Generated, and that is the point: a hand-written directive is a parallel structure over
|
|
8
|
+
* the manifest with nothing watching it, so an attribute added to an element would be
|
|
9
|
+
* typed in React, Vue and Svelte — which derive from the registry — and silently missing
|
|
10
|
+
* here. That happened, which is why this file is generated now.
|
|
11
|
+
*
|
|
12
|
+
* Outputs emit the event's DETAIL, not the `CustomEvent`, because
|
|
13
|
+
* `(selectChange)="pick($event.value)"` is the Angular idiom. Reach the event itself with
|
|
14
|
+
* a plain host listener when you need `stopPropagation`.
|
|
15
|
+
*/
|
|
16
|
+
import { Directive, ElementRef, EventEmitter, HostListener, Input, Output, booleanAttribute, inject, } from '@angular/core';
|
|
17
|
+
import { applyElementProps } from '@aparte/core';
|
|
18
|
+
import * as i0 from "@angular/core";
|
|
19
|
+
/**
|
|
20
|
+
* Writes one declared attribute onto the host element.
|
|
21
|
+
*
|
|
22
|
+
* `applyElementProps` is core's own rule, reused rather than reimplemented: a primitive
|
|
23
|
+
* goes through `setAttribute`, `true` becomes the empty presence attribute,
|
|
24
|
+
* `false`/`null`/`undefined` remove it, and only a value an attribute cannot carry is
|
|
25
|
+
* handed over as a property.
|
|
26
|
+
*/
|
|
27
|
+
class AparteElementBase {
|
|
28
|
+
host = inject((ElementRef));
|
|
29
|
+
write(name, value) {
|
|
30
|
+
applyElementProps(this.host.nativeElement, { [name]: value });
|
|
31
|
+
}
|
|
32
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AparteElementBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
33
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.25", type: AparteElementBase, isStandalone: true, ngImport: i0 });
|
|
34
|
+
}
|
|
35
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AparteElementBase, decorators: [{
|
|
36
|
+
type: Directive
|
|
37
|
+
}] });
|
|
38
|
+
/** `<aparte-model-selector>` — Selects an AI provider and a model. Renders an `<aparte-select>` with providers grouped into `<aparte-optgroup>`s — a single provider renders a flat list — which is what makes the BYOK pattern possible without core knowing about any vendor. */
|
|
39
|
+
export class AparteModelSelectorDirective extends AparteElementBase {
|
|
40
|
+
/** Writes the selection back through the config, so it survives a reload. */
|
|
41
|
+
set persist(v) { this.write('persist', v); }
|
|
42
|
+
/** Selects the first model as soon as one is available. */
|
|
43
|
+
set autoSelect(v) { this.write('auto-select', v); }
|
|
44
|
+
/** Adds the dropdown's filter field. */
|
|
45
|
+
set searchable(v) { this.write('searchable', v); }
|
|
46
|
+
/** Overrides the text shown while nothing is selected. */
|
|
47
|
+
set placeholder(v) { this.write('placeholder', v); }
|
|
48
|
+
/** The provider or the model changed; carries both ids. */
|
|
49
|
+
modelChange = new EventEmitter();
|
|
50
|
+
onModelChange(e) { this.modelChange.emit(e.detail); }
|
|
51
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AparteModelSelectorDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
52
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "19.2.25", type: AparteModelSelectorDirective, isStandalone: true, selector: "aparte-model-selector", inputs: { persist: ["persist", "persist", booleanAttribute], autoSelect: ["autoSelect", "autoSelect", booleanAttribute], searchable: ["searchable", "searchable", booleanAttribute], placeholder: "placeholder" }, outputs: { modelChange: "modelChange" }, host: { listeners: { "aparte-model-change": "onModelChange($event)" } }, usesInheritance: true, ngImport: i0 });
|
|
53
|
+
}
|
|
54
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: AparteModelSelectorDirective, decorators: [{
|
|
55
|
+
type: Directive,
|
|
56
|
+
args: [{ selector: 'aparte-model-selector', standalone: true }]
|
|
57
|
+
}], propDecorators: { persist: [{
|
|
58
|
+
type: Input,
|
|
59
|
+
args: [{ transform: booleanAttribute }]
|
|
60
|
+
}], autoSelect: [{
|
|
61
|
+
type: Input,
|
|
62
|
+
args: [{ transform: booleanAttribute }]
|
|
63
|
+
}], searchable: [{
|
|
64
|
+
type: Input,
|
|
65
|
+
args: [{ transform: booleanAttribute }]
|
|
66
|
+
}], placeholder: [{
|
|
67
|
+
type: Input
|
|
68
|
+
}], modelChange: [{
|
|
69
|
+
type: Output
|
|
70
|
+
}], onModelChange: [{
|
|
71
|
+
type: HostListener,
|
|
72
|
+
args: ['aparte-model-change', ['$event']]
|
|
73
|
+
}] } });
|
|
74
|
+
/**
|
|
75
|
+
* Every element directive, for one import in a standalone component.
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* @Component({ imports: [...APARTE_ELEMENT_DIRECTIVES], template: `…` })
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export const APARTE_ELEMENT_DIRECTIVES = [
|
|
82
|
+
AparteModelSelectorDirective,
|
|
83
|
+
];
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/aparte-model-selector.ts"],"sourcesContent":["/**\n * Aparté Model Selector\n *\n * Web Component for selecting an AI provider + model. Renders an `aparte-select`\n * primitive with providers grouped into `aparte-optgroup`s (a single provider\n * renders a flat list). Enables the BYOK (Bring Your Own Key) pattern.\n *\n * @element aparte-model-selector\n * @attr {boolean} auto-select - Auto-select the first model (default: false)\n * @attr {boolean} persist - Persist the selection through the config\n * @attr {boolean} searchable - Enable search in the dropdown\n * @attr {string} placeholder - Override the placeholder text\n *\n * @fires aparte-model-change - Fired when the selected model changes\n */\n\nimport {\n aparteGlobalConfig,\n escapeAttr,\n resolveConfig,\n type AparteConfig,\n type AparteConfigAware,\n AparteSelect,\n type AparteOptgroup,\n type AparteAIProvider,\n type AparteAIModel,\n type AparteModelChangeEventDetail,\n type AparteSelectChangeDetail,\n} from '@aparte/core';\n\ninterface ProviderModels {\n provider: AparteAIProvider;\n models: AparteAIModel[];\n}\n\n/**\n * Escape a value before it is interpolated into an HTML string (text node or\n * double-quoted attribute). Model names/ids come from a remote `/models`\n * endpoint and provider labels from consumer config — both hostile-by-default,\n * and both flow through `innerHTML` when the option list is (re)built.\n */\nfunction esc(value: unknown): string {\n // Coerce, then delegate: core owns the escaping. This local copy used to\n // inline it and, like two of its eight siblings across the scope, left the\n // apostrophe through — enough to break out of a single-quoted attribute.\n return escapeAttr(String(value ?? ''));\n}\n\nexport class AparteModelSelector extends HTMLElement implements AparteConfigAware {\n private _currentProviderId: string | null = null;\n private _currentModelId: string | null = null;\n private _providerModels: ProviderModels[] = [];\n private _aparteSelect: AparteSelect | null = null;\n private _isLoading = false;\n private _isRendering = false;\n private _expandedGroups: Set<string> = new Set();\n\n /**\n * Config governing THIS element — nearest instance boundary, else the global.\n *\n * Cached rather than resolved per call, because this element does not only\n * READ it: it holds a `subscribe()` registration keyed on the object. That\n * cache is only correct if something tells us when the boundary changes, and\n * under all four wrappers it does change after we connect —\n * `AparteChatHost.bind()` runs `attachConfig` from a post-mount hook. Hence\n * {@link AparteConfigAware}; without it this element served the global config's\n * providers to a chat that was given its own.\n */\n private _cfg: AparteConfig = aparteGlobalConfig;\n\n private _configUnsubscribe: (() => void) | null = null;\n\n // Bound handlers for cleanup\n private _boundHandleChange = this._handleChange.bind(this);\n private _handleOptgroupToggle = (e: Event): void => { void this._onOptgroupToggle(e); };\n\n static get observedAttributes(): string[] {\n return ['persist', 'auto-select', 'searchable', 'placeholder'];\n }\n\n async connectedCallback(): Promise<void> {\n this._cfg = resolveConfig(this);\n // Reset loading flag so a fresh mount always does a full load\n // (prevents a stale _isLoading=true from a previous mount blocking this one)\n this._isLoading = false;\n this._providerModels = [];\n\n this._setupEventListeners();\n\n // Seed selection from the resolved config first (handles race conditions)\n const config = this._cfg.getModelConfig();\n if (config.defaultProvider && config.defaultModel) {\n this._currentProviderId = config.defaultProvider;\n this._currentModelId = config.defaultModel;\n } else {\n this._loadPersistedSelection();\n }\n\n await this._loadAllProviderModels();\n this._render();\n\n this._subscribeToConfig();\n }\n\n /** Listen for configuration changes (e.g. from an onboarding flow). */\n private _subscribeToConfig(): void {\n this._configUnsubscribe?.();\n this._configUnsubscribe = this._cfg.subscribe(() => {\n void (async () => {\n const cfg = this._cfg.getModelConfig();\n\n // Guard: only react if the model config actually changed relative to our state\n if (cfg.defaultProvider === this._currentProviderId &&\n cfg.defaultModel === this._currentModelId &&\n this._providerModels.length > 0) {\n // …but a config change is not only a MODEL change. A language\n // switch fires this subscription too, hit this guard, and left\n // the placeholder in the previous language — the one string this\n // element takes from the locale, and the only one a user sees\n // before opening the list.\n //\n // The guard stays: a full `_render()` re-loads every provider's\n // models asynchronously and would close an open dropdown and\n // discard a typed search. So the cheap path is a relabel — one\n // attribute, no rebuild — which is the same contract a segment\n // renderer's `relabel` works under.\n this._relabel();\n return;\n }\n\n this._loadPersistedSelection();\n await this._loadAllProviderModels();\n this._render();\n })();\n });\n }\n\n /**\n * Re-apply the one string this element takes from the locale, in place.\n *\n * An explicit `placeholder` attribute still wins, exactly as it does at render\n * time: the app's own copy is not the locale's to overwrite.\n */\n private _relabel(): void {\n if (!this._aparteSelect) return;\n const fromLocale = this._cfg.getLocale()['modelSelectorPlaceholder'] || 'Select a model...';\n this._aparteSelect.setAttribute('placeholder', this.getAttribute('placeholder') || fromLocale);\n }\n\n disconnectedCallback(): void {\n this._aparteSelect?.removeEventListener('aparte-select-change', this._boundHandleChange);\n this.removeEventListener('aparte-optgroup-toggle', this._handleOptgroupToggle);\n this._configUnsubscribe?.();\n }\n\n /**\n * The boundary above us appeared or changed: move the subscription and reload,\n * because a different config means different providers and a different\n * selection.\n *\n * See {@link AparteConfigAware}. The element's own per-instance tests passed\n * before this existed only because they mount the boundary FIRST — the one\n * ordering no wrapper produces.\n */\n aparteConfigChanged(next: AparteConfig): void {\n this._configUnsubscribe?.();\n this._configUnsubscribe = null;\n this._cfg = next;\n if (!this.isConnected) return;\n void (async () => {\n this._isLoading = false;\n this._providerModels = [];\n const model = this._cfg.getModelConfig();\n if (model.defaultProvider && model.defaultModel) {\n this._currentProviderId = model.defaultProvider;\n this._currentModelId = model.defaultModel;\n } else {\n this._loadPersistedSelection();\n }\n await this._loadAllProviderModels();\n this._render();\n this._subscribeToConfig();\n })();\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected && !this._isLoading) {\n this._render();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Public API\n // ─────────────────────────────────────────────────────────────────────────\n\n /** Current provider ID. */\n get providerId(): string | null {\n return this._currentProviderId;\n }\n\n /** Current model ID. */\n get modelId(): string | null {\n return this._currentModelId;\n }\n\n /** Programmatically set the selection. */\n setSelection(providerId: string, modelId: string): void {\n this._currentProviderId = providerId;\n this._currentModelId = modelId;\n\n const compositeValue = `${providerId}::${modelId}`;\n if (this._aparteSelect) {\n this._aparteSelect.value = compositeValue;\n }\n\n this._emitChange();\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Data Loading\n // ─────────────────────────────────────────────────────────────────────────\n\n private async _loadAllProviderModels(): Promise<void> {\n if (this._isLoading) return;\n this._isLoading = true;\n\n try {\n const providers = this._cfg.getAIProviders();\n\n // Deduplicate providers by ID just in case\n const uniqueProviders = Array.from(new Map(providers.map(p => [p.id, p])).values());\n\n const config = this._cfg.getModelConfig();\n\n // Store in a temporary list to avoid mid-render state corruption.\n //\n // Indexed by REGISTRATION order, not filled by completion order. The\n // fetches run in parallel, so a `push` here ordered the dropdown — and\n // therefore what `auto-select` picks — by whichever /models endpoint\n // answered first. A cloud provider on a CDN beats a local server that\n // has to wake up, so an app registering `[OLLAMA, LMSTUDIO, OPENROUTER]`\n // could silently land on the paid one, and land on a different one on\n // the next reload. `auto-select` documents itself as \"the first model\";\n // first has to mean first, not fastest.\n const tempList: (ProviderModels | undefined)[] = new Array(uniqueProviders.length);\n\n // Fetch all providers in parallel\n await Promise.all(uniqueProviders.map(async (provider, i) => {\n try {\n const models = await this._cfg.refreshProviderModels(provider.id);\n\n // Apply model filters if configured\n const filters = config.modelFilters?.[provider.id];\n const filteredModels = filters?.length\n ? models.filter(m => filters.includes(m.id))\n : models;\n\n if (filteredModels.length > 0) {\n tempList[i] = { provider, models: filteredModels };\n }\n } catch (error) {\n console.warn(`[AparteModelSelector] Failed to load models for ${provider.id}:`, error);\n }\n }));\n\n // The holes are the providers that failed or returned nothing: dropped,\n // which keeps the order of the survivors.\n this._providerModels = tempList.filter((pm): pm is ProviderModels => pm !== undefined);\n } finally {\n this._isLoading = false;\n }\n }\n\n private async _onOptgroupToggle(e: Event): Promise<void> {\n const detail = (e as CustomEvent).detail;\n\n // Track expansion state\n if (detail.collapsed) {\n this._expandedGroups.delete(detail.label);\n return;\n }\n\n this._expandedGroups.add(detail.label);\n\n // Find which provider this optgroup belongs to\n const pm = this._providerModels.find(p => p.provider.getMetadata().name === detail.label);\n if (!pm || !pm.provider.fetchModels) return;\n\n // Show a loading state on the optgroup while we lazily fetch its models\n const groupEl = e.target as HTMLElement;\n if (groupEl && groupEl.tagName === 'APARTE-OPTGROUP') {\n (groupEl as AparteOptgroup).loading = true;\n }\n\n try {\n // Retrieve latest models via Config (provider-agnostic)\n const freshModels = await this._cfg.refreshProviderModels(pm.provider.id);\n\n if (freshModels && freshModels.length > 0) {\n pm.models = freshModels;\n this._render(true);\n }\n } catch (error) {\n console.error(`[AparteModelSelector] Lazy fetch failed for ${pm.provider.id}:`, error);\n } finally {\n const el = e.target as HTMLElement;\n if (el && el.tagName === 'APARTE-OPTGROUP') {\n (el as AparteOptgroup).loading = false;\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Rendering\n // ─────────────────────────────────────────────────────────────────────────\n\n private _render(keepOpen = false): void {\n if (this._isRendering) return;\n this._isRendering = true;\n\n try {\n this._renderImpl(keepOpen);\n } finally {\n this._isRendering = false;\n }\n }\n\n private _renderImpl(keepOpen: boolean): void {\n // Attribute overrides locale\n const localePlaceholder = this._cfg.getLocale()['modelSelectorPlaceholder'] || 'Select a model...';\n const placeholder = this.getAttribute('placeholder') || localePlaceholder;\n const searchable = this.hasAttribute('searchable');\n const autoSelect = this.hasAttribute('auto-select');\n\n // Capture current open state of aparte-select if it exists\n const wasOpen = keepOpen || this._aparteSelect?.hasAttribute('open');\n\n // Determine current value\n let currentValue = this._currentModelId ? `${this._currentProviderId}::${this._currentModelId}` : '';\n\n if (!currentValue && autoSelect) {\n const first = this._providerModels[0];\n const firstModel = first?.models[0];\n if (first && firstModel) {\n this._currentProviderId = first.provider.id;\n this._currentModelId = firstModel.id;\n currentValue = `${this._currentProviderId}::${this._currentModelId}`;\n // Emit the initial change once the element settles\n setTimeout(() => this._emitChange(), 0);\n }\n }\n\n // Build options HTML — single provider: flat list; multiple: grouped optgroups\n const only = this._providerModels[0];\n const singleProvider = this._providerModels.length === 1;\n const optionsHtml = singleProvider && only // safe-text: every value below goes through esc(); the tags are this file's own\n ? only.models.map(m => {\n const key = `${only.provider.id}::${m.id}`;\n return `<aparte-option value=\"${esc(key)}\">${esc(m.name)}</aparte-option>`;\n }).join('')\n : this._providerModels.map(pm => {\n const label = pm.provider.getMetadata().name;\n const isCollapsed = !this._expandedGroups.has(label);\n return `\n <aparte-optgroup\n label=\"${esc(label)}\"\n collapsible\n ${isCollapsed ? 'collapsed' : ''}\n >\n ${pm.models.map(m => {\n const key = `${pm.provider.id}::${m.id}`;\n return `<aparte-option value=\"${esc(key)}\">${esc(m.name)}</aparte-option>`;\n }).join('')}\n </aparte-optgroup>\n `;\n }).join('');\n\n if (this._aparteSelect) {\n // Non-destructive update of attributes\n this._aparteSelect.setAttribute('placeholder', placeholder);\n if (currentValue) this._aparteSelect.setAttribute('value', currentValue);\n else this._aparteSelect.removeAttribute('value');\n\n if (searchable) this._aparteSelect.setAttribute('searchable', '');\n else this._aparteSelect.removeAttribute('searchable');\n\n if (wasOpen) this._aparteSelect.setAttribute('open', '');\n else this._aparteSelect.removeAttribute('open');\n\n if (!singleProvider) this._aparteSelect.setAttribute('grouped', '');\n else this._aparteSelect.removeAttribute('grouped');\n\n // Update children cleanly: prefer direct container update if available\n const optionsContainer = this._aparteSelect.querySelector('.aparte-select-options');\n if (optionsContainer) {\n // Direct update (faster, skips the observer)\n optionsContainer.innerHTML = optionsHtml;\n\n // Force label re-evaluation: remove then re-set value so aparte-select\n // re-scans the newly injected options (setAttribute guard blocks same-value updates)\n if (currentValue) {\n this._aparteSelect.removeAttribute('value');\n this._aparteSelect.setAttribute('value', currentValue);\n }\n } else {\n // Fallback: self-healing mode\n const temp = document.createElement('div');\n temp.innerHTML = optionsHtml;\n const newChildren = Array.from(temp.children);\n\n const childrenToRemove = Array.from(this._aparteSelect.children).filter(c =>\n c.tagName === 'APARTE-OPTION' || c.tagName === 'APARTE-OPTGROUP'\n );\n childrenToRemove.forEach(c => c.remove());\n\n newChildren.forEach(c => this._aparteSelect?.appendChild(c));\n }\n\n // Critical: re-apply value after a microtask so AparteSelect has processed\n // the new options and can resolve the label.\n if (currentValue) {\n setTimeout(() => {\n if (this._aparteSelect) {\n this._aparteSelect.value = currentValue;\n }\n }, 0);\n }\n } else {\n // Full initial render\n this.innerHTML = `\n <aparte-select\n class=\"aparte-model-selector-select\"\n placeholder=\"${esc(placeholder)}\"\n ${currentValue ? `value=\"${esc(currentValue)}\"` : ''}\n ${searchable ? 'searchable' : ''}\n ${wasOpen ? 'open' : ''}\n ${!singleProvider ? 'grouped' : ''}\n >\n ${optionsHtml}\n </aparte-select>\n `;\n this._aparteSelect = this.querySelector('aparte-select');\n this._setupEventListeners();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Event Handling\n // ─────────────────────────────────────────────────────────────────────────\n\n private _setupEventListeners(): void {\n this._aparteSelect?.addEventListener('aparte-select-change', this._boundHandleChange);\n this.addEventListener('aparte-optgroup-toggle', this._handleOptgroupToggle);\n }\n\n private _handleChange(e: Event): void {\n const detail = (e as CustomEvent<AparteSelectChangeDetail>).detail;\n const previousProviderId = this._currentProviderId;\n const previousModelId = this._currentModelId;\n\n // Parse composite value \"providerId::modelId\"\n const [providerId, modelId] = detail.value.split('::');\n\n this._currentProviderId = providerId || null;\n this._currentModelId = modelId || null;\n\n this._emitChange(previousProviderId, previousModelId);\n }\n\n private _emitChange(previousProviderId?: string | null, previousModelId?: string | null): void {\n const detail: AparteModelChangeEventDetail = {\n providerId: this._currentProviderId || undefined,\n modelId: this._currentModelId || '',\n previousProviderId: previousProviderId || undefined,\n previousModelId: previousModelId || undefined,\n };\n\n this.dispatchEvent(new CustomEvent<AparteModelChangeEventDetail>('aparte-model-change', {\n bubbles: true,\n composed: true,\n detail,\n }));\n\n // Persist if enabled\n if (this.hasAttribute('persist')) {\n this._persistSelection();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Persistence (opt-in)\n // ─────────────────────────────────────────────────────────────────────────\n\n private _persistSelection(): void {\n if (!this._currentProviderId || !this._currentModelId) return;\n\n // Sync with the config — auto-save is handled by its setModelConfig()\n // if a AparteModelPreferenceProvider has been registered by the host app.\n const currentConfig = this._cfg.getModelConfig();\n if (currentConfig.defaultProvider === this._currentProviderId &&\n currentConfig.defaultModel === this._currentModelId) {\n return;\n }\n\n this._cfg.setModelConfig({\n defaultProvider: this._currentProviderId,\n defaultModel: this._currentModelId,\n });\n }\n\n private _loadPersistedSelection(): void {\n // The resolved config is the single source of truth. The host app is\n // responsible for restoring preferences into it (via restoreModelPreference())\n // before this component mounts.\n const config = this._cfg.getModelConfig();\n if (config.defaultProvider && config.defaultModel) {\n this._currentProviderId = config.defaultProvider;\n this._currentModelId = config.defaultModel;\n }\n // else: no-op — the config is empty\n }\n}\n\n// Register the custom element\nif (!customElements.get('aparte-model-selector')) {\n customElements.define('aparte-model-selector', AparteModelSelector);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'aparte-model-selector': AparteModelSelector;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/aparte-model-selector.ts"],"sourcesContent":["import {\n aparteGlobalConfig,\n escapeAttr,\n resolveConfig,\n type AparteConfig,\n type AparteConfigAware,\n AparteSelect,\n type AparteOptgroup,\n type AparteAIProvider,\n type AparteAIModel,\n type AparteModelChangeEventDetail,\n type AparteSelectChangeDetail,\n} from '@aparte/core';\n\ninterface ProviderModels {\n provider: AparteAIProvider;\n models: AparteAIModel[];\n}\n\n/**\n * Escape a value before it is interpolated into an HTML string (text node or\n * double-quoted attribute). Model names/ids come from a remote `/models`\n * endpoint and provider labels from consumer config — both hostile-by-default,\n * and both flow through `innerHTML` when the option list is (re)built.\n */\nfunction esc(value: unknown): string {\n // Coerce, then delegate: core owns the escaping. This local copy used to\n // inline it and, like two of its eight siblings across the scope, left the\n // apostrophe through — enough to break out of a single-quoted attribute.\n return escapeAttr(String(value ?? ''));\n}\n\n/**\n * Selects an AI provider and a model. Renders an `<aparte-select>` with providers\n * grouped into `<aparte-optgroup>`s — a single provider renders a flat list — which is\n * what makes the BYOK pattern possible without core knowing about any vendor.\n *\n * These tags sat at the top of the file, above the imports and a helper, so nothing\n * read them: TypeScript associates only the comment adjacent to the declaration. This\n * package ships no manifest of its own today (only `@aparte/core` runs `cem analyze`),\n * so the loss was invisible to tooling — but it is also what an editor shows on hover,\n * and what a typed framework wrapper is written from.\n *\n * @element aparte-model-selector\n * @attr {boolean} auto-select - Selects the first model as soon as one is available.\n * @attr {boolean} persist - Writes the selection back through the config, so it survives a reload.\n * @attr {boolean} searchable - Adds the dropdown's filter field.\n * @attr {string} placeholder - Overrides the text shown while nothing is selected.\n *\n * @fires {CustomEvent<AparteModelChangeEventDetail>} aparte-model-change - The provider or the model changed; carries both ids.\n *\n * @example\n * <!-- Mount it in the composer's toolbar; it reads the models the config already knows. -->\n * <aparte-composer-toolbar>\n * <aparte-model-selector searchable placeholder=\"Pick a model\"></aparte-model-selector>\n * </aparte-composer-toolbar>\n */\nexport class AparteModelSelector extends HTMLElement implements AparteConfigAware {\n private _currentProviderId: string | null = null;\n private _currentModelId: string | null = null;\n private _providerModels: ProviderModels[] = [];\n private _aparteSelect: AparteSelect | null = null;\n private _isLoading = false;\n private _isRendering = false;\n private _expandedGroups: Set<string> = new Set();\n\n /**\n * Config governing THIS element — nearest instance boundary, else the global.\n *\n * Cached rather than resolved per call, because this element does not only\n * READ it: it holds a `subscribe()` registration keyed on the object. That\n * cache is only correct if something tells us when the boundary changes, and\n * under all four wrappers it does change after we connect —\n * `AparteChatHost.bind()` runs `attachConfig` from a post-mount hook. Hence\n * {@link AparteConfigAware}; without it this element served the global config's\n * providers to a chat that was given its own.\n */\n private _cfg: AparteConfig = aparteGlobalConfig;\n\n private _configUnsubscribe: (() => void) | null = null;\n\n // Bound handlers for cleanup\n private _boundHandleChange = this._handleChange.bind(this);\n private _handleOptgroupToggle = (e: Event): void => { void this._onOptgroupToggle(e); };\n\n static get observedAttributes(): string[] {\n return ['persist', 'auto-select', 'searchable', 'placeholder'];\n }\n\n async connectedCallback(): Promise<void> {\n this._cfg = resolveConfig(this);\n // Reset loading flag so a fresh mount always does a full load\n // (prevents a stale _isLoading=true from a previous mount blocking this one)\n this._isLoading = false;\n this._providerModels = [];\n\n this._setupEventListeners();\n\n // Seed selection from the resolved config first (handles race conditions)\n const config = this._cfg.getModelConfig();\n if (config.defaultProvider && config.defaultModel) {\n this._currentProviderId = config.defaultProvider;\n this._currentModelId = config.defaultModel;\n } else {\n this._loadPersistedSelection();\n }\n\n await this._loadAllProviderModels();\n this._render();\n\n this._subscribeToConfig();\n }\n\n /** Listen for configuration changes (e.g. from an onboarding flow). */\n private _subscribeToConfig(): void {\n this._configUnsubscribe?.();\n this._configUnsubscribe = this._cfg.subscribe(() => {\n void (async () => {\n const cfg = this._cfg.getModelConfig();\n\n // Guard: only react if the model config actually changed relative to our state\n if (cfg.defaultProvider === this._currentProviderId &&\n cfg.defaultModel === this._currentModelId &&\n this._providerModels.length > 0) {\n // …but a config change is not only a MODEL change. A language\n // switch fires this subscription too, hit this guard, and left\n // the placeholder in the previous language — the one string this\n // element takes from the locale, and the only one a user sees\n // before opening the list.\n //\n // The guard stays: a full `_render()` re-loads every provider's\n // models asynchronously and would close an open dropdown and\n // discard a typed search. So the cheap path is a relabel — one\n // attribute, no rebuild — which is the same contract a segment\n // renderer's `relabel` works under.\n this._relabel();\n return;\n }\n\n this._loadPersistedSelection();\n await this._loadAllProviderModels();\n this._render();\n })();\n });\n }\n\n /**\n * Re-apply the one string this element takes from the locale, in place.\n *\n * An explicit `placeholder` attribute still wins, exactly as it does at render\n * time: the app's own copy is not the locale's to overwrite.\n */\n private _relabel(): void {\n if (!this._aparteSelect) return;\n const fromLocale = this._cfg.getLocale()['modelSelectorPlaceholder'] || 'Select a model...';\n this._aparteSelect.setAttribute('placeholder', this.getAttribute('placeholder') || fromLocale);\n }\n\n disconnectedCallback(): void {\n this._aparteSelect?.removeEventListener('aparte-select-change', this._boundHandleChange);\n this.removeEventListener('aparte-optgroup-toggle', this._handleOptgroupToggle);\n this._configUnsubscribe?.();\n }\n\n /**\n * The boundary above us appeared or changed: move the subscription and reload,\n * because a different config means different providers and a different\n * selection.\n *\n * See {@link AparteConfigAware}. The element's own per-instance tests passed\n * before this existed only because they mount the boundary FIRST — the one\n * ordering no wrapper produces.\n */\n aparteConfigChanged(next: AparteConfig): void {\n this._configUnsubscribe?.();\n this._configUnsubscribe = null;\n this._cfg = next;\n if (!this.isConnected) return;\n void (async () => {\n this._isLoading = false;\n this._providerModels = [];\n const model = this._cfg.getModelConfig();\n if (model.defaultProvider && model.defaultModel) {\n this._currentProviderId = model.defaultProvider;\n this._currentModelId = model.defaultModel;\n } else {\n this._loadPersistedSelection();\n }\n await this._loadAllProviderModels();\n this._render();\n this._subscribeToConfig();\n })();\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected && !this._isLoading) {\n this._render();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Public API\n // ─────────────────────────────────────────────────────────────────────────\n\n /** Current provider ID. */\n get providerId(): string | null {\n return this._currentProviderId;\n }\n\n /** Current model ID. */\n get modelId(): string | null {\n return this._currentModelId;\n }\n\n /** Programmatically set the selection. */\n setSelection(providerId: string, modelId: string): void {\n this._currentProviderId = providerId;\n this._currentModelId = modelId;\n\n const compositeValue = `${providerId}::${modelId}`;\n if (this._aparteSelect) {\n this._aparteSelect.value = compositeValue;\n }\n\n this._emitChange();\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Data Loading\n // ─────────────────────────────────────────────────────────────────────────\n\n private async _loadAllProviderModels(): Promise<void> {\n if (this._isLoading) return;\n this._isLoading = true;\n\n try {\n const providers = this._cfg.getAIProviders();\n\n // Deduplicate providers by ID just in case\n const uniqueProviders = Array.from(new Map(providers.map(p => [p.id, p])).values());\n\n const config = this._cfg.getModelConfig();\n\n // Store in a temporary list to avoid mid-render state corruption.\n //\n // Indexed by REGISTRATION order, not filled by completion order. The\n // fetches run in parallel, so a `push` here ordered the dropdown — and\n // therefore what `auto-select` picks — by whichever /models endpoint\n // answered first. A cloud provider on a CDN beats a local server that\n // has to wake up, so an app registering `[OLLAMA, LMSTUDIO, OPENROUTER]`\n // could silently land on the paid one, and land on a different one on\n // the next reload. `auto-select` documents itself as \"the first model\";\n // first has to mean first, not fastest.\n const tempList: (ProviderModels | undefined)[] = new Array(uniqueProviders.length);\n\n // Fetch all providers in parallel\n await Promise.all(uniqueProviders.map(async (provider, i) => {\n try {\n const models = await this._cfg.refreshProviderModels(provider.id);\n\n // Apply model filters if configured\n const filters = config.modelFilters?.[provider.id];\n const filteredModels = filters?.length\n ? models.filter(m => filters.includes(m.id))\n : models;\n\n if (filteredModels.length > 0) {\n tempList[i] = { provider, models: filteredModels };\n }\n } catch (error) {\n console.warn(`[AparteModelSelector] Failed to load models for ${provider.id}:`, error);\n }\n }));\n\n // The holes are the providers that failed or returned nothing: dropped,\n // which keeps the order of the survivors.\n this._providerModels = tempList.filter((pm): pm is ProviderModels => pm !== undefined);\n } finally {\n this._isLoading = false;\n }\n }\n\n private async _onOptgroupToggle(e: Event): Promise<void> {\n const detail = (e as CustomEvent).detail;\n\n // Track expansion state\n if (detail.collapsed) {\n this._expandedGroups.delete(detail.label);\n return;\n }\n\n this._expandedGroups.add(detail.label);\n\n // Find which provider this optgroup belongs to\n const pm = this._providerModels.find(p => p.provider.getMetadata().name === detail.label);\n if (!pm || !pm.provider.fetchModels) return;\n\n // Show a loading state on the optgroup while we lazily fetch its models\n const groupEl = e.target as HTMLElement;\n if (groupEl && groupEl.tagName === 'APARTE-OPTGROUP') {\n (groupEl as AparteOptgroup).loading = true;\n }\n\n try {\n // Retrieve latest models via Config (provider-agnostic)\n const freshModels = await this._cfg.refreshProviderModels(pm.provider.id);\n\n if (freshModels && freshModels.length > 0) {\n pm.models = freshModels;\n this._render(true);\n }\n } catch (error) {\n console.error(`[AparteModelSelector] Lazy fetch failed for ${pm.provider.id}:`, error);\n } finally {\n const el = e.target as HTMLElement;\n if (el && el.tagName === 'APARTE-OPTGROUP') {\n (el as AparteOptgroup).loading = false;\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Rendering\n // ─────────────────────────────────────────────────────────────────────────\n\n private _render(keepOpen = false): void {\n if (this._isRendering) return;\n this._isRendering = true;\n\n try {\n this._renderImpl(keepOpen);\n } finally {\n this._isRendering = false;\n }\n }\n\n private _renderImpl(keepOpen: boolean): void {\n // Attribute overrides locale\n const localePlaceholder = this._cfg.getLocale()['modelSelectorPlaceholder'] || 'Select a model...';\n const placeholder = this.getAttribute('placeholder') || localePlaceholder;\n const searchable = this.hasAttribute('searchable');\n const autoSelect = this.hasAttribute('auto-select');\n\n // Capture current open state of aparte-select if it exists\n const wasOpen = keepOpen || this._aparteSelect?.hasAttribute('open');\n\n // Determine current value\n let currentValue = this._currentModelId ? `${this._currentProviderId}::${this._currentModelId}` : '';\n\n if (!currentValue && autoSelect) {\n const first = this._providerModels[0];\n const firstModel = first?.models[0];\n if (first && firstModel) {\n this._currentProviderId = first.provider.id;\n this._currentModelId = firstModel.id;\n currentValue = `${this._currentProviderId}::${this._currentModelId}`;\n // Emit the initial change once the element settles\n setTimeout(() => this._emitChange(), 0);\n }\n }\n\n // Build options HTML — single provider: flat list; multiple: grouped optgroups\n const only = this._providerModels[0];\n const singleProvider = this._providerModels.length === 1;\n const optionsHtml = singleProvider && only // safe-text: every value below goes through esc(); the tags are this file's own\n ? only.models.map(m => {\n const key = `${only.provider.id}::${m.id}`;\n return `<aparte-option value=\"${esc(key)}\">${esc(m.name)}</aparte-option>`;\n }).join('')\n : this._providerModels.map(pm => {\n const label = pm.provider.getMetadata().name;\n const isCollapsed = !this._expandedGroups.has(label);\n return `\n <aparte-optgroup\n label=\"${esc(label)}\"\n collapsible\n ${isCollapsed ? 'collapsed' : ''}\n >\n ${pm.models.map(m => {\n const key = `${pm.provider.id}::${m.id}`;\n return `<aparte-option value=\"${esc(key)}\">${esc(m.name)}</aparte-option>`;\n }).join('')}\n </aparte-optgroup>\n `;\n }).join('');\n\n if (this._aparteSelect) {\n // Non-destructive update of attributes\n this._aparteSelect.setAttribute('placeholder', placeholder);\n if (currentValue) this._aparteSelect.setAttribute('value', currentValue);\n else this._aparteSelect.removeAttribute('value');\n\n if (searchable) this._aparteSelect.setAttribute('searchable', '');\n else this._aparteSelect.removeAttribute('searchable');\n\n if (wasOpen) this._aparteSelect.setAttribute('open', '');\n else this._aparteSelect.removeAttribute('open');\n\n if (!singleProvider) this._aparteSelect.setAttribute('grouped', '');\n else this._aparteSelect.removeAttribute('grouped');\n\n // Update children cleanly: prefer direct container update if available\n const optionsContainer = this._aparteSelect.querySelector('.aparte-select-options');\n if (optionsContainer) {\n // Direct update (faster, skips the observer)\n optionsContainer.innerHTML = optionsHtml;\n\n // Force label re-evaluation: remove then re-set value so aparte-select\n // re-scans the newly injected options (setAttribute guard blocks same-value updates)\n if (currentValue) {\n this._aparteSelect.removeAttribute('value');\n this._aparteSelect.setAttribute('value', currentValue);\n }\n } else {\n // Fallback: self-healing mode\n const temp = document.createElement('div');\n temp.innerHTML = optionsHtml;\n const newChildren = Array.from(temp.children);\n\n const childrenToRemove = Array.from(this._aparteSelect.children).filter(c =>\n c.tagName === 'APARTE-OPTION' || c.tagName === 'APARTE-OPTGROUP'\n );\n childrenToRemove.forEach(c => c.remove());\n\n newChildren.forEach(c => this._aparteSelect?.appendChild(c));\n }\n\n // Critical: re-apply value after a microtask so AparteSelect has processed\n // the new options and can resolve the label.\n if (currentValue) {\n setTimeout(() => {\n if (this._aparteSelect) {\n this._aparteSelect.value = currentValue;\n }\n }, 0);\n }\n } else {\n // Full initial render\n this.innerHTML = `\n <aparte-select\n class=\"aparte-model-selector-select\"\n placeholder=\"${esc(placeholder)}\"\n ${currentValue ? `value=\"${esc(currentValue)}\"` : ''}\n ${searchable ? 'searchable' : ''}\n ${wasOpen ? 'open' : ''}\n ${!singleProvider ? 'grouped' : ''}\n >\n ${optionsHtml}\n </aparte-select>\n `;\n this._aparteSelect = this.querySelector('aparte-select');\n this._setupEventListeners();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Event Handling\n // ─────────────────────────────────────────────────────────────────────────\n\n private _setupEventListeners(): void {\n this._aparteSelect?.addEventListener('aparte-select-change', this._boundHandleChange);\n this.addEventListener('aparte-optgroup-toggle', this._handleOptgroupToggle);\n }\n\n private _handleChange(e: Event): void {\n const detail = (e as CustomEvent<AparteSelectChangeDetail>).detail;\n const previousProviderId = this._currentProviderId;\n const previousModelId = this._currentModelId;\n\n // Parse composite value \"providerId::modelId\"\n const [providerId, modelId] = detail.value.split('::');\n\n this._currentProviderId = providerId || null;\n this._currentModelId = modelId || null;\n\n this._emitChange(previousProviderId, previousModelId);\n }\n\n private _emitChange(previousProviderId?: string | null, previousModelId?: string | null): void {\n const detail: AparteModelChangeEventDetail = {\n providerId: this._currentProviderId || undefined,\n modelId: this._currentModelId || '',\n previousProviderId: previousProviderId || undefined,\n previousModelId: previousModelId || undefined,\n };\n\n this.dispatchEvent(new CustomEvent<AparteModelChangeEventDetail>('aparte-model-change', {\n bubbles: true,\n composed: true,\n detail,\n }));\n\n // Persist if enabled\n if (this.hasAttribute('persist')) {\n this._persistSelection();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Persistence (opt-in)\n // ─────────────────────────────────────────────────────────────────────────\n\n private _persistSelection(): void {\n if (!this._currentProviderId || !this._currentModelId) return;\n\n // Sync with the config — auto-save is handled by its setModelConfig()\n // if a AparteModelPreferenceProvider has been registered by the host app.\n const currentConfig = this._cfg.getModelConfig();\n if (currentConfig.defaultProvider === this._currentProviderId &&\n currentConfig.defaultModel === this._currentModelId) {\n return;\n }\n\n this._cfg.setModelConfig({\n defaultProvider: this._currentProviderId,\n defaultModel: this._currentModelId,\n });\n }\n\n private _loadPersistedSelection(): void {\n // The resolved config is the single source of truth. The host app is\n // responsible for restoring preferences into it (via restoreModelPreference())\n // before this component mounts.\n const config = this._cfg.getModelConfig();\n if (config.defaultProvider && config.defaultModel) {\n this._currentProviderId = config.defaultProvider;\n this._currentModelId = config.defaultModel;\n }\n // else: no-op — the config is empty\n }\n}\n\n// Register the custom element\nif (!customElements.get('aparte-model-selector')) {\n customElements.define('aparte-model-selector', AparteModelSelector);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'aparte-model-selector': AparteModelSelector;\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<aparte-model-selector>` as a typed JSX intrinsic. Import once, anywhere:
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import '@aparte/plugin-model-selector/react';
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* ## Why this lives here and not in `@aparte/react`
|
|
9
|
+
*
|
|
10
|
+
* A wrapper types what it depends on, and `@aparte/react` depends on no plugin. It once
|
|
11
|
+
* did — for a day — and the reason that was wrong is the reason this file exists: a
|
|
12
|
+
* third-party plugin's author cannot add a line to `@aparte/react`, so typing OUR plugin
|
|
13
|
+
* there gave aparté's packages a privilege theirs could never have.
|
|
14
|
+
*
|
|
15
|
+
* Putting it in the plugin makes the property you actually want fall out of the module
|
|
16
|
+
* graph: install this package and the tag is typed, don't and it isn't. TypeScript
|
|
17
|
+
* enforces that; nobody has to remember it.
|
|
18
|
+
*
|
|
19
|
+
* ## Why a subpath rather than the main entry
|
|
20
|
+
*
|
|
21
|
+
* A `declare module 'react'` block only compiles where React's types resolve. In the
|
|
22
|
+
* main entry it would break every Vue and Svelte consumer of this plugin with
|
|
23
|
+
* `TS2664: Invalid module name in augmentation` — which is exactly the error the docs'
|
|
24
|
+
* own snippet checker raised when this was first written into a shared file.
|
|
25
|
+
*
|
|
26
|
+
* The attribute facts come from `./generated/element-attributes.js`, generated from this
|
|
27
|
+
* package's own custom-elements manifest, so this file states no fact of its own and has
|
|
28
|
+
* nothing to keep in step. `AparteTemplateAttrs` from core supplies the template
|
|
29
|
+
* spelling — a presence attribute is `'' | null | undefined`, never `boolean`, because
|
|
30
|
+
* React stringifies what it sets on a custom element and `searchable={false}` would
|
|
31
|
+
* render `searchable="false"`, which an element testing `hasAttribute` reads as ON.
|
|
32
|
+
*/
|
|
33
|
+
import type * as React from 'react';
|
|
34
|
+
import type { AparteTemplateAttrs } from '@aparte/core';
|
|
35
|
+
import type { AparteElementAttributes, AparteElementTagName } from './generated/element-attributes.js';
|
|
36
|
+
type PluginIntrinsics = {
|
|
37
|
+
[K in AparteElementTagName]: React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & AparteTemplateAttrs<AparteElementAttributes[K]>;
|
|
38
|
+
};
|
|
39
|
+
declare global {
|
|
40
|
+
namespace JSX {
|
|
41
|
+
interface IntrinsicElements extends PluginIntrinsics {
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
declare module 'react' {
|
|
46
|
+
namespace JSX {
|
|
47
|
+
interface IntrinsicElements extends PluginIntrinsics {
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEvG,KAAK,gBAAgB,GAAG;KACnB,CAAC,IAAI,oBAAoB,GACtB,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,GACrE,mBAAmB,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;CACxD,CAAC;AAEF,OAAO,CAAC,MAAM,CAAC;IAEX,UAAU,GAAG,CAAC;QACV,UAAU,iBAAkB,SAAQ,gBAAgB;SAAG;KAC1D;CACJ;AAED,OAAO,QAAQ,OAAO,CAAC;IAEnB,UAAU,GAAG,CAAC;QACV,UAAU,iBAAkB,SAAQ,gBAAgB;SAAG;KAC1D;CACJ;AAED,OAAO,EAAE,CAAC"}
|
package/dist/react.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/dist/svelte.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<aparte-model-selector>` typed for Svelte markup. Import once, anywhere:
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import '@aparte/plugin-model-selector/svelte';
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* A subpath rather than the main entry, and in the plugin rather than in
|
|
9
|
+
* `@aparte/svelte`: see `./react.ts` for both arguments.
|
|
10
|
+
*
|
|
11
|
+
* The `on:` handlers are derived from `HTMLElementEventMap`, which `@aparte/core`
|
|
12
|
+
* augments with every aparté event including this element's `aparte-model-change` — so
|
|
13
|
+
* there is no event list here either.
|
|
14
|
+
*/
|
|
15
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
16
|
+
import type { AparteTemplateAttrs } from '@aparte/core';
|
|
17
|
+
import type { AparteElementAttributes, AparteElementTagName } from './generated/element-attributes.js';
|
|
18
|
+
type AparteEventName = Extract<keyof HTMLElementEventMap, `aparte-${string}`>;
|
|
19
|
+
type PluginHandlers = {
|
|
20
|
+
[K in AparteEventName as `on:${K}`]?: (event: HTMLElementEventMap[K]) => void;
|
|
21
|
+
};
|
|
22
|
+
type PluginElements = {
|
|
23
|
+
[K in AparteElementTagName]: HTMLAttributes<HTMLElement> & AparteTemplateAttrs<AparteElementAttributes[K]> & PluginHandlers;
|
|
24
|
+
};
|
|
25
|
+
declare module 'svelte/elements' {
|
|
26
|
+
interface SvelteHTMLElements extends PluginElements {
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svelte.d.ts","sourceRoot":"","sources":["../src/svelte.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEvG,KAAK,eAAe,GAAG,OAAO,CAAC,MAAM,mBAAmB,EAAE,UAAU,MAAM,EAAE,CAAC,CAAC;AAE9E,KAAK,cAAc,GAAG;KACjB,CAAC,IAAI,eAAe,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC,KAAK,IAAI;CAChF,CAAC;AAEF,KAAK,cAAc,GAAG;KACjB,CAAC,IAAI,oBAAoB,GACtB,cAAc,CAAC,WAAW,CAAC,GAAG,mBAAmB,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,GAAG,cAAc;CACrG,CAAC;AAEF,OAAO,QAAQ,iBAAiB,CAAC;IAC7B,UAAU,kBAAmB,SAAQ,cAAc;KAAG;CACzD;AAED,OAAO,EAAE,CAAC"}
|
package/dist/svelte.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svelte.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/dist/vue.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<aparte-model-selector>` typed for Vue templates. Import once, anywhere:
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* import '@aparte/plugin-model-selector/vue';
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* A subpath rather than the main entry, and in the plugin rather than in `@aparte/vue`:
|
|
9
|
+
* see `./react.ts` for both arguments, which are the same ones. In short — a `declare
|
|
10
|
+
* module 'vue'` only compiles where Vue's types resolve, and a wrapper types only what
|
|
11
|
+
* it depends on.
|
|
12
|
+
*
|
|
13
|
+
* The attributes come from this package's own generated registry, so nothing here is a
|
|
14
|
+
* fact that can fall behind the element.
|
|
15
|
+
*/
|
|
16
|
+
import type { DefineComponent } from 'vue';
|
|
17
|
+
import type { AparteTemplateAttrs } from '@aparte/core';
|
|
18
|
+
import type { AparteElementAttributes, AparteElementTagName } from './generated/element-attributes.js';
|
|
19
|
+
type PluginComponents = {
|
|
20
|
+
[K in AparteElementTagName]: DefineComponent<AparteTemplateAttrs<AparteElementAttributes[K]>>;
|
|
21
|
+
};
|
|
22
|
+
declare module 'vue' {
|
|
23
|
+
interface GlobalComponents extends PluginComponents {
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue.d.ts","sourceRoot":"","sources":["../src/vue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,KAAK,CAAC;AAC3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEvG,KAAK,gBAAgB,GAAG;KACnB,CAAC,IAAI,oBAAoB,GAAG,eAAe,CAAC,mBAAmB,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC;CAChG,CAAC;AAEF,OAAO,QAAQ,KAAK,CAAC;IACjB,UAAU,gBAAiB,SAAQ,gBAAgB;KAAG;CACzD;AAED,OAAO,EAAE,CAAC"}
|
package/dist/vue.js
ADDED
package/dist/vue.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aparte/plugin-model-selector",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Provider + model selector web component (<aparte-model-selector>) for aparté — grouped dropdown, BYOK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": true,
|
|
@@ -17,6 +17,26 @@
|
|
|
17
17
|
"types": "./dist/index.d.ts",
|
|
18
18
|
"import": "./dist/index.js",
|
|
19
19
|
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./react": {
|
|
22
|
+
"@aparte-workspace/source": "./src/react.ts",
|
|
23
|
+
"types": "./dist/react.d.ts",
|
|
24
|
+
"default": "./dist/react.js"
|
|
25
|
+
},
|
|
26
|
+
"./vue": {
|
|
27
|
+
"@aparte-workspace/source": "./src/vue.ts",
|
|
28
|
+
"types": "./dist/vue.d.ts",
|
|
29
|
+
"default": "./dist/vue.js"
|
|
30
|
+
},
|
|
31
|
+
"./svelte": {
|
|
32
|
+
"@aparte-workspace/source": "./src/svelte.ts",
|
|
33
|
+
"types": "./dist/svelte.d.ts",
|
|
34
|
+
"default": "./dist/svelte.js"
|
|
35
|
+
},
|
|
36
|
+
"./angular": {
|
|
37
|
+
"@aparte-workspace/source": "./src/angular.ts",
|
|
38
|
+
"types": "./dist/angular.d.ts",
|
|
39
|
+
"default": "./dist/angular.js"
|
|
20
40
|
}
|
|
21
41
|
},
|
|
22
42
|
"files": [
|
|
@@ -28,12 +48,24 @@
|
|
|
28
48
|
"node": ">=18"
|
|
29
49
|
},
|
|
30
50
|
"peerDependencies": {
|
|
31
|
-
"@
|
|
51
|
+
"@angular/core": "^19.2.0",
|
|
52
|
+
"@aparte/core": ">=0.7.0 <1.0.0",
|
|
53
|
+
"react": "^19.2.7",
|
|
54
|
+
"svelte": "^4.2.0",
|
|
55
|
+
"vue": "^3.5.0"
|
|
32
56
|
},
|
|
33
57
|
"devDependencies": {
|
|
58
|
+
"@angular/compiler": "^19.2.0",
|
|
59
|
+
"@angular/compiler-cli": "^19.2.0",
|
|
60
|
+
"@angular/core": "^19.2.0",
|
|
61
|
+
"@custom-elements-manifest/analyzer": "^0.11.0",
|
|
62
|
+
"@types/react": "^19.2.17",
|
|
63
|
+
"react": "^19.2.7",
|
|
64
|
+
"svelte": "^4.2.0",
|
|
34
65
|
"typescript": "^5.4.0",
|
|
35
66
|
"vite": "^6.0.0",
|
|
36
|
-
"
|
|
67
|
+
"vue": "^3.5.0",
|
|
68
|
+
"@aparte/core": "0.11.0"
|
|
37
69
|
},
|
|
38
70
|
"keywords": [
|
|
39
71
|
"aparte",
|
|
@@ -51,12 +83,29 @@
|
|
|
51
83
|
"bugs": {
|
|
52
84
|
"url": "https://github.com/apartejs/aparte/issues"
|
|
53
85
|
},
|
|
86
|
+
"customElements": "dist/custom-elements.json",
|
|
87
|
+
"peerDependenciesMeta": {
|
|
88
|
+
"react": {
|
|
89
|
+
"optional": true
|
|
90
|
+
},
|
|
91
|
+
"vue": {
|
|
92
|
+
"optional": true
|
|
93
|
+
},
|
|
94
|
+
"svelte": {
|
|
95
|
+
"optional": true
|
|
96
|
+
},
|
|
97
|
+
"@angular/core": {
|
|
98
|
+
"optional": true
|
|
99
|
+
}
|
|
100
|
+
},
|
|
54
101
|
"scripts": {
|
|
55
102
|
"dev": "vite",
|
|
56
|
-
"build": "vite build && tsc -b --emitDeclarationOnly --force",
|
|
103
|
+
"build": "vite build && tsc -b --emitDeclarationOnly --force && ngc -p tsconfig.angular.json && pnpm run analyze",
|
|
57
104
|
"preview": "vite preview",
|
|
58
105
|
"test": "vitest",
|
|
59
106
|
"test:run": "vitest run",
|
|
60
|
-
"test:coverage": "vitest run --coverage"
|
|
107
|
+
"test:coverage": "vitest run --coverage",
|
|
108
|
+
"analyze": "cem analyze",
|
|
109
|
+
"gen": "pnpm run analyze && node ../../../scripts/gen-element-bindings.mjs packages/plugins/model-selector --registry packages/plugins/model-selector/src/generated --angular packages/plugins/model-selector/src/generated"
|
|
61
110
|
}
|
|
62
111
|
}
|