@webx-ui/core 0.7.0 → 0.8.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.
@@ -12,6 +12,7 @@ declare const __VLS_component: import('vue').DefineComponent<ContainerProps, {},
12
12
  as: string | import('vue').Component;
13
13
  direction: import('./types').ContainerDirection;
14
14
  fullHeight: boolean;
15
+ viewport: boolean;
15
16
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
16
17
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
17
18
  export default _default;
@@ -8,6 +8,16 @@ export interface ContainerProps {
8
8
  direction?: ContainerDirection;
9
9
  /** Makes the container at least as tall as the viewport. For the outermost one. */
10
10
  fullHeight?: boolean;
11
+ /**
12
+ * Makes the container exactly as tall as the viewport and stops it growing, so
13
+ * that what scrolls is a pane inside it rather than the page. This is the shape an
14
+ * admin shell has: a header that stays put and a main column that scrolls under
15
+ * it. Pair it with `scroll` on the `WxMain` inside.
16
+ *
17
+ * `fullHeight` is the other answer — at least the viewport, with the page itself
18
+ * scrolling. Use that for a document, this for an application.
19
+ */
20
+ viewport?: boolean;
11
21
  /** The element to render. */
12
22
  as?: string | Component;
13
23
  }
@@ -0,0 +1,73 @@
1
+ import { ListDetailProps } from './types';
2
+ type __VLS_Props = ListDetailProps;
3
+ type __VLS_PublicProps = {
4
+ 'open'?: boolean;
5
+ 'filtersOpen'?: boolean;
6
+ } & __VLS_Props;
7
+ declare function __VLS_template(): {
8
+ attrs: Partial<{}>;
9
+ slots: Readonly<{
10
+ /** What narrows the list: views, folders, filters. The column is optional. */
11
+ filters?: (props: {
12
+ inline: boolean;
13
+ close: () => void;
14
+ }) => unknown;
15
+ /** The records. */
16
+ list?: (props: {
17
+ filtersInline: boolean;
18
+ openFilters: () => void;
19
+ }) => unknown;
20
+ /** The record that is open. */
21
+ detail?: (props: {
22
+ inline: boolean;
23
+ back: () => void;
24
+ }) => unknown;
25
+ /** Shown in the pane's place while nothing is selected. */
26
+ empty?: () => unknown;
27
+ }> & {
28
+ /** What narrows the list: views, folders, filters. The column is optional. */
29
+ filters?: (props: {
30
+ inline: boolean;
31
+ close: () => void;
32
+ }) => unknown;
33
+ /** The records. */
34
+ list?: (props: {
35
+ filtersInline: boolean;
36
+ openFilters: () => void;
37
+ }) => unknown;
38
+ /** The record that is open. */
39
+ detail?: (props: {
40
+ inline: boolean;
41
+ back: () => void;
42
+ }) => unknown;
43
+ /** Shown in the pane's place while nothing is selected. */
44
+ empty?: () => unknown;
45
+ };
46
+ refs: {
47
+ root: HTMLDivElement;
48
+ };
49
+ rootEl: HTMLDivElement;
50
+ };
51
+ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
52
+ declare const __VLS_component: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
53
+ "update:open": (value: boolean) => any;
54
+ "update:filtersOpen": (value: boolean) => any;
55
+ }, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
56
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
57
+ "onUpdate:filtersOpen"?: ((value: boolean) => any) | undefined;
58
+ }>, {
59
+ filtersWidth: number | string;
60
+ listWidth: number | string;
61
+ detailMin: number;
62
+ filtersTitle: string;
63
+ detailLabel: string;
64
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
65
+ root: HTMLDivElement;
66
+ }, HTMLDivElement>;
67
+ declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
68
+ export default _default;
69
+ type __VLS_WithTemplateSlots<T, S> = T & {
70
+ new (): {
71
+ $slots: S;
72
+ };
73
+ };
@@ -0,0 +1,2 @@
1
+ export { default as WxListDetail } from './ListDetail';
2
+ export type * from './types';
@@ -0,0 +1,19 @@
1
+ export interface ListDetailProps {
2
+ /**
3
+ * Width of the column that narrows the list: saved views, filters, folders.
4
+ * The column is only rendered when the `filters` slot is used.
5
+ */
6
+ filtersWidth?: number | string;
7
+ /** Width of the list of records. */
8
+ listWidth?: number | string;
9
+ /**
10
+ * The narrowest the detail pane may be. It is what the two thresholds are made
11
+ * of: the filters column folds away when it would push the pane under this, and
12
+ * the pane stops standing beside the list when it no longer fits either.
13
+ */
14
+ detailMin?: number;
15
+ /** Heading of the panel the filters move into once the column does not fit. */
16
+ filtersTitle?: string;
17
+ /** Accessible name of the panel the detail opens in on a narrow screen. */
18
+ detailLabel?: string;
19
+ }
@@ -10,7 +10,9 @@ declare function __VLS_template(): {
10
10
  slots: {
11
11
  default?(_: {}): any;
12
12
  };
13
- refs: {};
13
+ refs: {
14
+ list: HTMLUListElement;
15
+ };
14
16
  rootEl: HTMLUListElement;
15
17
  };
16
18
  type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
@@ -27,9 +29,13 @@ declare const __VLS_component: import('vue').DefineComponent<__VLS_PublicProps,
27
29
  label: string;
28
30
  collapsed: boolean;
29
31
  mode: import('./types').MenuMode;
32
+ overflow: import('./types').MenuOverflow;
33
+ overflowTitle: string;
30
34
  accordion: boolean;
31
35
  autoExpand: boolean;
32
- }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLUListElement>;
36
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
37
+ list: HTMLUListElement;
38
+ }, HTMLUListElement>;
33
39
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
34
40
  export default _default;
35
41
  type __VLS_WithTemplateSlots<T, S> = T & {
@@ -0,0 +1,30 @@
1
+ import { PropType, VNode } from 'vue';
2
+ /**
3
+ * The entries of a menu as a flat list, so they can be counted and split between the
4
+ * bar and the branch that holds what did not fit.
5
+ *
6
+ * A `v-for` arrives as one fragment holding many entries, and a `v-if` that is false
7
+ * arrives as a comment. Both have to go: the list is lined up index for index against
8
+ * the `<li>` elements the browser actually laid out, and a comment is not one.
9
+ */
10
+ export declare function flattenEntries(nodes: VNode[]): VNode[];
11
+ /**
12
+ * Renders vnodes that have already been created — the two halves of a split menu.
13
+ *
14
+ * It exists because a template can render a slot but not a slice of one, and the
15
+ * entries must be rendered *once*: an entry that appeared in both halves would
16
+ * register itself twice and report the wrong branch to the menu above it.
17
+ */
18
+ export declare const WxMenuNodes: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
19
+ nodes: {
20
+ type: PropType<VNode[]>;
21
+ required: true;
22
+ };
23
+ }>, () => VNode<import('vue').RendererNode, import('vue').RendererElement, {
24
+ [key: string]: any;
25
+ }>[], {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
26
+ nodes: {
27
+ type: PropType<VNode[]>;
28
+ required: true;
29
+ };
30
+ }>> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
@@ -1,10 +1,20 @@
1
1
  import { MenuMode, MenuSize, MenuValue } from '../../composables/useMenu';
2
2
  export type { MenuMode, MenuSize, MenuValue };
3
+ /**
4
+ * What a bar does with entries it has no room for: move them into a branch at the
5
+ * end of it, or let the bar scroll sideways. Vertical menus ignore this — a column
6
+ * has as much room as it needs.
7
+ */
8
+ export type MenuOverflow = 'menu' | 'scroll';
3
9
  export interface MenuProps {
4
10
  /** A sidebar down the page, or a bar across the top of it. */
5
11
  mode?: MenuMode;
6
12
  /** Row height and text size. */
7
13
  size?: MenuSize;
14
+ /** What a bar does with the entries that do not fit across it. */
15
+ overflow?: MenuOverflow;
16
+ /** Title of the branch those entries move into. */
17
+ overflowTitle?: string;
8
18
  /**
9
19
  * The icon rail: labels are hidden and submenus open as flyouts beside the rail.
10
20
  * Vertical menus only — there is nothing to collapse in a bar.
@@ -38,6 +38,7 @@ export * from './Input';
38
38
  export * from './InputNumber';
39
39
  export * from './Kanban';
40
40
  export * from './Link';
41
+ export * from './ListDetail';
41
42
  export * from './Main';
42
43
  export * from './Menu';
43
44
  export * from './MenuGroup';
@@ -0,0 +1,35 @@
1
+ import { ComputedRef } from 'vue';
2
+ /**
3
+ * Splits what the caller wrote on a control between its two halves.
4
+ *
5
+ * Every control here sets `inheritAttrs: false` and hands `$attrs` to the element
6
+ * inside it, so that `placeholder`, `autocomplete`, `data-*` and the ARIA attributes
7
+ * reach the real `<input>` rather than the wrapper around it. Taken literally that
8
+ * sends `class` and `style` there too, and both are then in the wrong place:
9
+ *
10
+ * - The caller means the control, not its input. `class="w-60"` on a `<wx-select>` is
11
+ * asking for a narrower select, and the select is the wrapper.
12
+ * - A parent's scoped CSS cannot reach it. Scoped styles carry an attribute that is
13
+ * stamped on a child component's *root*, so a class that lands three elements deep
14
+ * matches nothing — silently.
15
+ * - And where `$attrs` is bound to an element that is only sometimes rendered — the
16
+ * search field of a filterable `WxSelect` — the class disappears altogether.
17
+ *
18
+ * So `class` and `style` go on the root, and everything else goes on the control.
19
+ *
20
+ * ```ts
21
+ * const { rootAttrs, controlAttrs } = useControlAttrs()
22
+ * ```
23
+ * ```vue
24
+ * <div :class="classes" v-bind="rootAttrs">
25
+ * <input v-bind="controlAttrs" />
26
+ * </div>
27
+ * ```
28
+ */
29
+ export interface ControlAttrs {
30
+ /** `class` and `style` — for the wrapper the caller can see. */
31
+ rootAttrs: ComputedRef<Record<string, unknown>>;
32
+ /** Everything else — for the element the browser focuses and reads out. */
33
+ controlAttrs: ComputedRef<Record<string, unknown>>;
34
+ }
35
+ export declare function useControlAttrs(): ControlAttrs;
@@ -0,0 +1,17 @@
1
+ import { Ref } from 'vue';
2
+ /**
3
+ * The width of an element, kept up to date — the measurement every layout that
4
+ * answers to its own box rather than to the window is built on.
5
+ *
6
+ * `0` means nothing has been measured yet: on the server, and until the element is
7
+ * mounted. Treat it as "assume the roomy case" rather than as zero width, the way
8
+ * `useResponsiveShell` does — the real number arrives before paint.
9
+ *
10
+ * ```ts
11
+ * const el = ref<HTMLElement | null>(null)
12
+ * const width = useElementWidth(el)
13
+ * ```
14
+ *
15
+ * Pass nothing to measure the page itself.
16
+ */
17
+ export declare function useElementWidth(target?: Ref<HTMLElement | null | undefined>): Ref<number>;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from './components';
2
2
  export { WebxUI, type WebxUiOptions } from './plugin';
3
3
  export type { ControlSize, ControlStatus, ValidationErrors } from './composables/useFormField';
4
+ export { useControlAttrs, type ControlAttrs } from './composables/useControlAttrs';
5
+ export { useElementWidth } from './composables/useElementWidth';
4
6
  export { useResponsiveShell, shellLayoutFor, type ResponsiveShell, type ResponsiveShellOptions, type ShellLayout, } from './composables/useResponsiveShell';