mn-angular-lib 1.0.163 → 1.0.165

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.
@@ -13825,6 +13825,193 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
13825
13825
  type: Output
13826
13826
  }] } });
13827
13827
 
13828
+ /**
13829
+ * Styling for {@link MnSegmented}, expressed as tailwind-variants slots so the
13830
+ * template pulls one class string per role.
13831
+ *
13832
+ * The control is a track with the active choice raised out of it, rather than a
13833
+ * row of loose buttons: the segments share one bordered surface, so they read as
13834
+ * one control with one answer instead of several independent actions. Theme
13835
+ * tokens only, so it holds up in both light and dark.
13836
+ */
13837
+ const mnSegmentedVariants = tv({
13838
+ slots: {
13839
+ root: 'inline-flex items-center gap-0.5 border border-base-300 bg-base-200 p-0.5',
13840
+ segment: 'inline-flex items-center justify-center gap-1.5 cursor-pointer select-none ' +
13841
+ 'whitespace-nowrap border border-transparent transition-colors ' +
13842
+ 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary ' +
13843
+ 'disabled:opacity-50 disabled:pointer-events-none',
13844
+ },
13845
+ variants: {
13846
+ /**
13847
+ * Corner rounding of the track, with the segments rounded one step tighter so
13848
+ * a filled segment nests inside the track's own corner instead of poking out
13849
+ * of it. Token names match mn-button's; `full` makes a pill, where track and
13850
+ * segment share the same fully-rounded ends.
13851
+ */
13852
+ borderRadius: {
13853
+ none: { root: 'rounded-none', segment: 'rounded-none' },
13854
+ xs: { root: 'rounded-xs', segment: 'rounded-none' },
13855
+ sm: { root: 'rounded-sm', segment: 'rounded-xs' },
13856
+ md: { root: 'rounded-md', segment: 'rounded-sm' },
13857
+ lg: { root: 'rounded-lg', segment: 'rounded-md' },
13858
+ xl: { root: 'rounded-xl', segment: 'rounded-lg' },
13859
+ two_xl: { root: 'rounded-2xl', segment: 'rounded-xl' },
13860
+ three_xl: { root: 'rounded-3xl', segment: 'rounded-2xl' },
13861
+ four_xl: { root: 'rounded-4xl', segment: 'rounded-3xl' },
13862
+ full: { root: 'rounded-full', segment: 'rounded-full' },
13863
+ },
13864
+ size: {
13865
+ sm: { segment: 'px-2.5 py-1 text-sm' },
13866
+ md: { segment: 'px-3 py-1.5 text-base' },
13867
+ },
13868
+ /**
13869
+ * Stretch the track and share its width evenly between the segments.
13870
+ *
13871
+ * The segments grow from a zero basis but keep their automatic minimum, so a
13872
+ * justified control inside an auto-width parent still asks for the room its
13873
+ * labels need. Letting them shrink below their content (`min-w-0`) made the
13874
+ * parent resolve to a narrower box and truncated the labels instead.
13875
+ */
13876
+ justified: {
13877
+ true: { root: 'flex w-full', segment: 'flex-1' },
13878
+ false: {},
13879
+ },
13880
+ /**
13881
+ * The picked segment. Filled rather than merely tinted: the control is often
13882
+ * the only thing on its row, so the answer has to be readable at a glance
13883
+ * without comparing two subtle shades.
13884
+ */
13885
+ active: {
13886
+ true: { segment: 'bg-primary text-primary-content' },
13887
+ false: { segment: 'bg-transparent text-base-content hover:bg-base-content/10' },
13888
+ },
13889
+ },
13890
+ defaultVariants: {
13891
+ size: 'md',
13892
+ borderRadius: 'lg',
13893
+ justified: false,
13894
+ active: false,
13895
+ },
13896
+ });
13897
+
13898
+ /** Icon edge length per size, so a segment's glyph matches its own text. */
13899
+ const ICON_SIZE = { sm: 16, md: 18 };
13900
+ /**
13901
+ * A segmented control: two or three mutually exclusive choices sharing one
13902
+ * track, of which exactly one is active — a view switch (list ⇄ calendar), a
13903
+ * scope switch (mine ⇄ everyone), a range switch (week ⇄ month).
13904
+ *
13905
+ * The selection is **controlled**: the component renders whatever
13906
+ * {@link value} says and emits {@link valueChange} on a click, so the consumer's
13907
+ * own state stays the single source of truth for what is on screen. It keeps no
13908
+ * copy of the selection, and — unlike `mn-tab` — it does not mirror one into the
13909
+ * URL, so it can sit on a page that already has a tab bar without the two
13910
+ * fighting over the query string.
13911
+ *
13912
+ * For switching between panes of a page, reach for `mn-tab`; this is for
13913
+ * switching how one pane is rendered.
13914
+ */
13915
+ class MnSegmented {
13916
+ /** The choices and how the group is labelled and scaled. */
13917
+ dataSource;
13918
+ /**
13919
+ * Value of the active segment. No value (or one naming no segment) leaves the
13920
+ * control with nothing active, which is what an unresolved selection should
13921
+ * look like — the component never picks one on the consumer's behalf.
13922
+ */
13923
+ value;
13924
+ /**
13925
+ * Whether the segments stretch to fill the available width. Defaults to false,
13926
+ * so the control hugs its content and can be parked at the end of a row; turn
13927
+ * it on where it should span its container, typically on a narrow screen.
13928
+ */
13929
+ justified = false;
13930
+ /** Emits the picked segment's value. The consumer decides what to do with it. */
13931
+ valueChange = new EventEmitter();
13932
+ /** Resolves this control's own accessible names against the app's bundle. */
13933
+ lang = inject(MnLanguageService);
13934
+ /** Resolved slot classes for the current size and layout. */
13935
+ get styles() {
13936
+ return mnSegmentedVariants({
13937
+ size: this.dataSource.size,
13938
+ borderRadius: this.dataSource.borderRadius,
13939
+ justified: this.justified,
13940
+ });
13941
+ }
13942
+ /** Icon edge length matching the control's text size. */
13943
+ get iconSize() {
13944
+ return ICON_SIZE[this.dataSource.size ?? 'md'];
13945
+ }
13946
+ /** Accessible name of the group, or null when the consumer named nothing. */
13947
+ get groupLabel() {
13948
+ const key = this.dataSource.ariaLabel;
13949
+ return key ? this.lang.translate(key) : null;
13950
+ }
13951
+ /**
13952
+ * Whether `item` is the active choice.
13953
+ * @param item - The segment to test.
13954
+ */
13955
+ isActive(item) {
13956
+ return item.value === this.value;
13957
+ }
13958
+ /**
13959
+ * Classes for one segment, which differ only in whether it is the active one.
13960
+ * @param item - The segment to style.
13961
+ */
13962
+ segmentClass(item) {
13963
+ return mnSegmentedVariants({
13964
+ size: this.dataSource.size,
13965
+ borderRadius: this.dataSource.borderRadius,
13966
+ justified: this.justified,
13967
+ active: this.isActive(item),
13968
+ }).segment();
13969
+ }
13970
+ /**
13971
+ * Accessible name for an icon-only segment, or null when the segment shows a
13972
+ * label — that label already names it, and a second name would only compete.
13973
+ * @param item - The segment to name.
13974
+ */
13975
+ segmentLabel(item) {
13976
+ if (item.label || !item.ariaLabel)
13977
+ return null;
13978
+ return this.lang.translate(item.ariaLabel);
13979
+ }
13980
+ /**
13981
+ * Whether an icon was supplied as a `TemplateRef` rather than lucide icon data.
13982
+ * @param value - The icon to test.
13983
+ */
13984
+ isTemplateRef(value) {
13985
+ return value instanceof TemplateRef;
13986
+ }
13987
+ /**
13988
+ * Announces a click. Re-picking the active segment is silent: it is not a
13989
+ * change, and a consumer that reloads on every emission would refetch for
13990
+ * nothing.
13991
+ * @param item - The segment that was clicked.
13992
+ */
13993
+ select(item) {
13994
+ if (item.disabled || this.isActive(item))
13995
+ return;
13996
+ this.valueChange.emit(item.value);
13997
+ }
13998
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnSegmented, deps: [], target: i0.ɵɵFactoryTarget.Component });
13999
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: MnSegmented, isStandalone: true, selector: "mn-segmented", inputs: { dataSource: "dataSource", value: "value", justified: "justified" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<!-- One control, one answer: `role=\"group\"` with `aria-pressed` per segment, so\n the picked choice is announced as pressed rather than as a plain button\n nobody can tell the state of. Not a radiogroup \u2014 these are buttons that act\n immediately, not a value being edited inside a form. -->\n<div [attr.aria-label]=\"groupLabel\" [class]=\"styles.root()\" role=\"group\">\n @for (item of dataSource.items; track item.value) {\n <button\n (click)=\"select(item)\"\n [attr.aria-label]=\"segmentLabel(item)\"\n [attr.aria-pressed]=\"isActive(item)\"\n [class]=\"segmentClass(item)\"\n [disabled]=\"item.disabled ?? false\"\n type=\"button\"\n >\n @if (item.icon; as icon) {\n <span class=\"inline-flex shrink-0 items-center\">\n <!-- A caller's template, else lucide data rendered at the size that\n matches this control's text \u2014 the same icon convention the\n dropdown's actions use. -->\n @if (isTemplateRef(icon)) {\n <ng-container [ngTemplateOutlet]=\"icon\"></ng-container>\n } @else {\n <svg [lucideIcon]=\"$any(icon)\" [size]=\"iconSize\"></svg>\n }\n </span>\n }\n @if (item.label; as label) {\n <span class=\"truncate\">{{ label | mnTranslate }}</span>\n }\n </button>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }, { kind: "pipe", type: MnTranslatePipe, name: "mnTranslate" }] });
14000
+ }
14001
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MnSegmented, decorators: [{
14002
+ type: Component,
14003
+ args: [{ selector: 'mn-segmented', standalone: true, imports: [MnTranslatePipe, NgTemplateOutlet, LucideDynamicIcon], template: "<!-- One control, one answer: `role=\"group\"` with `aria-pressed` per segment, so\n the picked choice is announced as pressed rather than as a plain button\n nobody can tell the state of. Not a radiogroup \u2014 these are buttons that act\n immediately, not a value being edited inside a form. -->\n<div [attr.aria-label]=\"groupLabel\" [class]=\"styles.root()\" role=\"group\">\n @for (item of dataSource.items; track item.value) {\n <button\n (click)=\"select(item)\"\n [attr.aria-label]=\"segmentLabel(item)\"\n [attr.aria-pressed]=\"isActive(item)\"\n [class]=\"segmentClass(item)\"\n [disabled]=\"item.disabled ?? false\"\n type=\"button\"\n >\n @if (item.icon; as icon) {\n <span class=\"inline-flex shrink-0 items-center\">\n <!-- A caller's template, else lucide data rendered at the size that\n matches this control's text \u2014 the same icon convention the\n dropdown's actions use. -->\n @if (isTemplateRef(icon)) {\n <ng-container [ngTemplateOutlet]=\"icon\"></ng-container>\n } @else {\n <svg [lucideIcon]=\"$any(icon)\" [size]=\"iconSize\"></svg>\n }\n </span>\n }\n @if (item.label; as label) {\n <span class=\"truncate\">{{ label | mnTranslate }}</span>\n }\n </button>\n }\n</div>\n" }]
14004
+ }], propDecorators: { dataSource: [{
14005
+ type: Input,
14006
+ args: [{ required: true }]
14007
+ }], value: [{
14008
+ type: Input
14009
+ }], justified: [{
14010
+ type: Input
14011
+ }], valueChange: [{
14012
+ type: Output
14013
+ }] } });
14014
+
13828
14015
  /**
13829
14016
  * Injection token for the base URL used by all CRUD service requests.
13830
14017
  *
@@ -14326,5 +14513,5 @@ function enableMnPreviewMode(configService, langService, allowedOrigins) {
14326
14513
  * Generated bundle index. Do not edit.
14327
14514
  */
14328
14515
 
14329
- export { API_BASE_URL, ActionStyle, BackdropMode, BaseModalBuilder, CALENDAR_CONFIG, CALENDAR_DATE_FORMATTER, CalendarDayComponent, CalendarEventComponent, CalendarEventDefaultComponent, CalendarEventLayoutService, CalendarMonthComponent, CalendarUtility, CalendarView, CalendarViewComponent, CalendarWeekComponent, CloseMode, ColumnSortType, ConfirmationModalBuilder, ConfirmationTone, CrudService, CustomModalBuilder, DEFAULT_CALENDAR_CONFIG, DEFAULT_MN_ALERT_CONFIG, DefaultCalendarDateFormatter, FieldAppearance, FieldKind, FormLayoutMode, FormModalBuilder, KeyboardMode, MN_ALERT_CONFIG, MN_CALENDAR_COMPONENT_NAME, MN_CALENDAR_CONFIG, MN_CHECKBOX_CONFIG, MN_DATETIME_CONFIG, MN_DROPDOWN_CONFIG, MN_HAPTICS, MN_ICON_MAP, MN_INPUT_FIELD_CONFIG, MN_INSTANCE_ID, MN_LIB_DUAL_HORIZONTAL_IMAGE, MN_MODAL_ACTION_ICONS, MN_MULTI_SELECT_CONFIG, MN_SECTION_PATH, MN_SELECT_CONFIG, MN_TEXTAREA_CONFIG, MODAL_ACTION_ICON_SIZE, MODAL_ACTION_ICON_SIZE_SM, MnAlertOutletComponent, MnAlertService, MnAlertStore, MnBadge, MnBottomSheet, MnBreadcrumbs, MnButton, MnCheckbox, MnCollectionBase, MnCollectionPagination, MnCollectionState, MnConfigService, MnConfirmationBodyComponent, MnCustomBodyHostComponent, MnDateSelectorBar, MnDatetime, MnDropdown, MnDualHorizontalImage, MnFileInput, MnFormBodyComponent, MnGrid, MnHiddenBelowDirective, MnHttpService, MnIcon, MnIconAttributes, MnInformationCard, MnInputField, MnInstanceDirective, MnKeyboard, MnLanguageService, MnList, MnModalRef, MnModalService, MnModalShellComponent, MnMultiSelect, MnRichTextEditor, MnSectionDirective, MnSelect, MnSelectableCollectionBase, MnShowAboveDirective, MnShowBelowDirective, MnSkeleton, MnTabComponent, MnTable, MnTextarea, MnTranslatePipe, MnWizardBodyComponent, ModalBuilder, ModalCloseReason, ModalIntent, ModalKind, ModalSize, NavigationDirection, OptionState, SelectionMode, StepBuilder, StepState, SubmitMode, UpcomingEventRowComponent, UpcomingEventsComponent, ValidationCode, ValidationStatus, WizardFlowMode, WizardModalBuilder, dateTimeAdapter, defaultFilterPredicate, defaultIconForStyle, defaultTextAdapter, emptyFilterValue, enableMnPreviewMode, isFilterValueActive, isTranslatable, matchesColumnFilter, mnAlertVariants, mnBadgeVariants, mnBreadcrumbsVariants, mnButtonVariants, mnCheckboxVariants, mnCheckboxWrapperVariants, mnDatetimeVariants, mnDropdownTriggerVariants, mnFileInputVariants, mnIconVariants, mnInformationCardVariants, mnInputFieldVariants, mnMultiSelectVariants, mnSelectVariants, mnSkeletonVariants, mnTextareaVariants, numberAdapter, pickAdapter, provideMnAlerts, provideMnCalendarConfig, provideMnComponentConfig, provideMnConfig, provideMnLanguage, resolveCalendarConfig, resolveFilterableValue };
14516
+ export { API_BASE_URL, ActionStyle, BackdropMode, BaseModalBuilder, CALENDAR_CONFIG, CALENDAR_DATE_FORMATTER, CalendarDayComponent, CalendarEventComponent, CalendarEventDefaultComponent, CalendarEventLayoutService, CalendarMonthComponent, CalendarUtility, CalendarView, CalendarViewComponent, CalendarWeekComponent, CloseMode, ColumnSortType, ConfirmationModalBuilder, ConfirmationTone, CrudService, CustomModalBuilder, DEFAULT_CALENDAR_CONFIG, DEFAULT_MN_ALERT_CONFIG, DefaultCalendarDateFormatter, FieldAppearance, FieldKind, FormLayoutMode, FormModalBuilder, KeyboardMode, MN_ALERT_CONFIG, MN_CALENDAR_COMPONENT_NAME, MN_CALENDAR_CONFIG, MN_CHECKBOX_CONFIG, MN_DATETIME_CONFIG, MN_DROPDOWN_CONFIG, MN_HAPTICS, MN_ICON_MAP, MN_INPUT_FIELD_CONFIG, MN_INSTANCE_ID, MN_LIB_DUAL_HORIZONTAL_IMAGE, MN_MODAL_ACTION_ICONS, MN_MULTI_SELECT_CONFIG, MN_SECTION_PATH, MN_SELECT_CONFIG, MN_TEXTAREA_CONFIG, MODAL_ACTION_ICON_SIZE, MODAL_ACTION_ICON_SIZE_SM, MnAlertOutletComponent, MnAlertService, MnAlertStore, MnBadge, MnBottomSheet, MnBreadcrumbs, MnButton, MnCheckbox, MnCollectionBase, MnCollectionPagination, MnCollectionState, MnConfigService, MnConfirmationBodyComponent, MnCustomBodyHostComponent, MnDateSelectorBar, MnDatetime, MnDropdown, MnDualHorizontalImage, MnFileInput, MnFormBodyComponent, MnGrid, MnHiddenBelowDirective, MnHttpService, MnIcon, MnIconAttributes, MnInformationCard, MnInputField, MnInstanceDirective, MnKeyboard, MnLanguageService, MnList, MnModalRef, MnModalService, MnModalShellComponent, MnMultiSelect, MnRichTextEditor, MnSectionDirective, MnSegmented, MnSelect, MnSelectableCollectionBase, MnShowAboveDirective, MnShowBelowDirective, MnSkeleton, MnTabComponent, MnTable, MnTextarea, MnTranslatePipe, MnWizardBodyComponent, ModalBuilder, ModalCloseReason, ModalIntent, ModalKind, ModalSize, NavigationDirection, OptionState, SelectionMode, StepBuilder, StepState, SubmitMode, UpcomingEventRowComponent, UpcomingEventsComponent, ValidationCode, ValidationStatus, WizardFlowMode, WizardModalBuilder, dateTimeAdapter, defaultFilterPredicate, defaultIconForStyle, defaultTextAdapter, emptyFilterValue, enableMnPreviewMode, isFilterValueActive, isTranslatable, matchesColumnFilter, mnAlertVariants, mnBadgeVariants, mnBreadcrumbsVariants, mnButtonVariants, mnCheckboxVariants, mnCheckboxWrapperVariants, mnDatetimeVariants, mnDropdownTriggerVariants, mnFileInputVariants, mnIconVariants, mnInformationCardVariants, mnInputFieldVariants, mnMultiSelectVariants, mnSegmentedVariants, mnSelectVariants, mnSkeletonVariants, mnTextareaVariants, numberAdapter, pickAdapter, provideMnAlerts, provideMnCalendarConfig, provideMnComponentConfig, provideMnConfig, provideMnLanguage, resolveCalendarConfig, resolveFilterableValue };
14330
14517
  //# sourceMappingURL=mn-angular-lib.mjs.map