@milaboratories/uikit 2.9.0 → 2.10.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.
Files changed (45) hide show
  1. package/.turbo/turbo-build.log +49 -48
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/.turbo/turbo-type-check.log +1 -1
  4. package/CHANGELOG.md +13 -0
  5. package/dist/components/DataTable/TableComponent.vue.js +4 -4
  6. package/dist/components/PlAutocomplete/PlAutocomplete.vue.js +1 -1
  7. package/dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue.js +1 -1
  8. package/dist/components/PlDropdown/PlDropdown.vue.js +1 -1
  9. package/dist/components/PlDropdownLegacy/PlDropdownLegacy.vue.js +1 -1
  10. package/dist/components/PlDropdownMulti/PlDropdownMulti.vue.js +1 -1
  11. package/dist/components/PlFileInput/PlFileInput.vue.js +1 -1
  12. package/dist/components/PlLogView/PlLogView.vue.js +1 -1
  13. package/dist/components/PlNumberField/PlNumberField.vue.js +1 -1
  14. package/dist/components/PlSlideModal/PlPureSlideModal.vue.js +4 -4
  15. package/dist/components/PlTextArea/PlTextArea.vue.js +1 -1
  16. package/dist/components/PlTextField/PlTextField.vue.js +1 -1
  17. package/dist/layout/PlBlockPage/PlBlockPage.vue.d.ts +28 -2
  18. package/dist/layout/PlBlockPage/PlBlockPage.vue.d.ts.map +1 -1
  19. package/dist/layout/PlBlockPage/PlBlockPage.vue.js +7 -58
  20. package/dist/layout/PlBlockPage/PlBlockPage.vue.js.map +1 -1
  21. package/dist/layout/PlBlockPage/PlBlockPage.vue2.js +87 -2
  22. package/dist/layout/PlBlockPage/PlBlockPage.vue2.js.map +1 -1
  23. package/dist/layout/PlBlockPage/PlBlockPage.vue3.js +13 -0
  24. package/dist/layout/PlBlockPage/PlBlockPage.vue3.js.map +1 -0
  25. package/dist/layout/PlBlockPage/PlBlockPageTitleTeleportTarget.d.ts +2 -0
  26. package/dist/layout/PlBlockPage/PlBlockPageTitleTeleportTarget.d.ts.map +1 -0
  27. package/dist/layout/PlBlockPage/PlBlockPageTitleTeleportTarget.js +6 -0
  28. package/dist/layout/PlBlockPage/PlBlockPageTitleTeleportTarget.js.map +1 -0
  29. package/dist/layout/PlBlockPage/usePlBlockPageTitleTeleportTarget.d.ts +1 -1
  30. package/dist/layout/PlBlockPage/usePlBlockPageTitleTeleportTarget.d.ts.map +1 -1
  31. package/dist/layout/PlBlockPage/usePlBlockPageTitleTeleportTarget.js +10 -11
  32. package/dist/layout/PlBlockPage/usePlBlockPageTitleTeleportTarget.js.map +1 -1
  33. package/dist/utils/DoubleContour.vue3.js +1 -1
  34. package/package.json +6 -6
  35. package/src/layout/PlBlockPage/PlBlockPage.vue +92 -23
  36. package/src/layout/PlBlockPage/PlBlockPageTitleTeleportTarget.ts +3 -0
  37. package/src/layout/PlBlockPage/pl-block-page.scss +3 -8
  38. package/src/layout/PlBlockPage/usePlBlockPageTitleTeleportTarget.ts +6 -11
  39. package/dist/layout/PlBlockPage/PlBlockPageTitleTeleportId.d.ts +0 -2
  40. package/dist/layout/PlBlockPage/PlBlockPageTitleTeleportId.d.ts.map +0 -1
  41. package/dist/layout/PlBlockPage/PlBlockPageTitleTeleportId.js +0 -6
  42. package/dist/layout/PlBlockPage/PlBlockPageTitleTeleportId.js.map +0 -1
  43. package/dist/utils/DoubleContour.vue2.js +0 -23
  44. package/dist/utils/DoubleContour.vue2.js.map +0 -1
  45. package/src/layout/PlBlockPage/PlBlockPageTitleTeleportId.ts +0 -3
@@ -3,7 +3,7 @@
3
3
  import { defineComponent as E, useSlots as S, ref as v, computed as a, onMounted as $, createElementBlock as s, openBlock as o, createElementVNode as n, createCommentVNode as i, normalizeClass as C, withDirectives as N, createVNode as q, createBlock as g, unref as d, toDisplayString as c, withCtx as D, renderSlot as b, vModelText as M } from "vue";
4
4
 
5
5
  import j from "../PlTooltip/PlTooltip.vue.js";
6
- import H from "../../utils/DoubleContour.vue2.js";
6
+ import H from "../../utils/DoubleContour.vue.js";
7
7
 
8
8
  import { useLabelNotch as P } from "../../utils/useLabelNotch.js";
9
9
  import { useValidation as T } from "../../utils/useValidation.js";
@@ -3,7 +3,7 @@
3
3
  import { defineComponent as I, mergeModels as N, useSlots as $, useModel as O, ref as h, reactive as T, computed as i, createElementBlock as d, openBlock as a, createElementVNode as p, createCommentVNode as n, normalizeClass as j, withDirectives as z, createVNode as L, createBlock as f, unref as c, toDisplayString as m, withCtx as U, renderSlot as E, vModelDynamic as A, withModifiers as V } from "vue";
4
4
  import G from "../../assets/images/required.svg.js";
5
5
  import { getErrorMessage as H } from "../../helpers/error.js";
6
- import J from "../../utils/DoubleContour.vue2.js";
6
+ import J from "../../utils/DoubleContour.vue.js";
7
7
 
8
8
  import { useLabelNotch as K } from "../../utils/useLabelNotch.js";
9
9
  import { useValidation as Q } from "../../utils/useValidation.js";
@@ -1,6 +1,16 @@
1
1
  import { PlPlaceholderProps } from '../PlPlaceholder';
2
2
  /** Root block page component */
3
3
  declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
4
+ subtitle?: string;
5
+ } & {
6
+ /**
7
+ * Page title (won't be displayed if `title` slot is also provided)
8
+ */
9
+ title?: string;
10
+ /**
11
+ * Text to display when subtitle is empty
12
+ */
13
+ subtitlePlaceholder?: string;
4
14
  /**
5
15
  * If `true` body gutters are removed
6
16
  */
@@ -9,7 +19,19 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
9
19
  * If defined, a loading overlay is displayed on the page body (over all default slot content)
10
20
  */
11
21
  bodyLoading?: PlPlaceholderProps["variant"] | PlPlaceholderProps;
12
- }, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
22
+ }, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
23
+ "update:subtitle": (value: string) => any;
24
+ }, string, import('vue').PublicProps, Readonly<{
25
+ subtitle?: string;
26
+ } & {
27
+ /**
28
+ * Page title (won't be displayed if `title` slot is also provided)
29
+ */
30
+ title?: string;
31
+ /**
32
+ * Text to display when subtitle is empty
33
+ */
34
+ subtitlePlaceholder?: string;
13
35
  /**
14
36
  * If `true` body gutters are removed
15
37
  */
@@ -18,7 +40,11 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
18
40
  * If defined, a loading overlay is displayed on the page body (over all default slot content)
19
41
  */
20
42
  bodyLoading?: PlPlaceholderProps["variant"] | PlPlaceholderProps;
21
- }> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>, {
43
+ }> & Readonly<{
44
+ "onUpdate:subtitle"?: ((value: string) => any) | undefined;
45
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
46
+ teleportTarget: HTMLDivElement;
47
+ }, HTMLDivElement>, {
22
48
  title?(_: {}): any;
23
49
  'after-title'?(_: {}): any;
24
50
  append?(_: {}): any;
@@ -1 +1 @@
1
- {"version":3,"file":"PlBlockPage.vue.d.ts","sourceRoot":"","sources":["../../../src/layout/PlBlockPage/PlBlockPage.vue"],"names":[],"mappings":"AA0EA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,EAAuC,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAGhG,gCAAgC;;IAK9B;;OAEG;oBACa,OAAO;IACvB;;OAEG;kBACW,kBAAkB,CAAC,SAAS,CAAC,GAAG,kBAAkB;;IAPhE;;OAEG;oBACa,OAAO;IACvB;;OAEG;kBACW,kBAAkB,CAAC,SAAS,CAAC,GAAG,kBAAkB;;mBAoFvC,GAAG;2BACK,GAAG;oBACV,GAAG;qBACF,GAAG;;AAlGhC,wBA4IK;AASL,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"PlBlockPage.vue.d.ts","sourceRoot":"","sources":["../../../src/layout/PlBlockPage/PlBlockPage.vue"],"names":[],"mappings":"AA+IA,OAAO,sBAAsB,CAAC;AAE9B,OAAO,EAAE,KAAK,kBAAkB,EAAuC,MAAM,kBAAkB,CAAC;AAGhG,gCAAgC;;eA8CnB,MAAM;;IAzCjB;;OAEG;YACK,MAAM;IACd;;OAEG;0BACmB,MAAM;IAC5B;;OAEG;oBACa,OAAO;IACvB;;OAEG;kBACW,kBAAkB,CAAC,SAAS,CAAC,GAAG,kBAAkB;;;;eA0BrD,MAAM;;IAzCjB;;OAEG;YACK,MAAM;IACd;;OAEG;0BACmB,MAAM;IAC5B;;OAEG;oBACa,OAAO;IACvB;;OAEG;kBACW,kBAAkB,CAAC,SAAS,CAAC,GAAG,kBAAkB;;;;;;mBAiIvC,GAAG;2BACK,GAAG;oBACV,GAAG;qBACD,GAAG;;AAvJjC,wBAsMK;AAgBL,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
@@ -1,61 +1,10 @@
1
- (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".pl-block-page{--pl-block-page-body-padding: var(--main-spacing, 24px);padding:var(--container-spacing);background-color:var(--bg-elevated-01);height:100%;max-width:100%;display:grid;grid-template-rows:auto minmax(0,1fr)}.pl-block-page.noBodyGutters{--pl-block-page-body-padding: 0}.pl-block-page__title{height:80px;display:flex;align-items:center;gap:12px;padding:20px 24px;min-width:0;max-width:100%}.pl-block-page__title__default{flex:1;min-width:0;max-width:100%;margin:0;color:var(--txt-01);display:flex;flex-direction:row;align-items:center;gap:12px}.pl-block-page__title__default>span{font-size:28px;font-weight:500;line-height:36px;letter-spacing:-.56px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;max-width:100%;display:inline-block}.pl-block-page__title__append{margin-left:auto;display:flex;align-items:center;gap:2px}.pl-block-page__title__append__teleport{display:flex;align-items:center;gap:2px}.pl-block-page__body{max-width:100%;display:flex;flex-direction:column;gap:var(--gap-v);padding:var(--pl-block-page-body-padding);--thumb-color: var(--ic-02);overflow-y:auto;overflow-x:auto}.pl-block-page__body::-webkit-scrollbar{width:var(--scrollbar-width, 6px);height:5px;background-color:transparent;display:block}.pl-block-page__body::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.pl-block-page__body::-webkit-scrollbar-thumb:hover{--thumb-color: var(--border-color-focus)}")),document.head.appendChild(e)}}catch(a){console.error("vite-plugin-css-injected-by-js",a)}})();
2
- import { defineComponent as u, useSlots as m, computed as v, createElementBlock as o, openBlock as l, normalizeClass as f, createElementVNode as t, unref as d, withDirectives as c, renderSlot as s, createVNode as y, normalizeProps as g, guardReactiveProps as b, vShow as h, normalizeStyle as k } from "vue";
3
- import { PlBlockPageTitleTeleportId as P } from "./PlBlockPageTitleTeleportId.js";
4
-
5
- import { PL_PLACEHOLDER_TEXTS as B } from "../PlPlaceholder/index.js";
6
- import L from "../PlPlaceholder/PlPlaceholder.vue.js";
7
- const T = {
8
- key: 0,
9
- class: "pl-block-page__title"
10
- }, E = { class: "pl-block-page__title__default" }, S = { class: "pl-block-page__title__append" }, A = ["id"], G = { key: 1 }, N = { class: "pl-block-page__body" }, $ = {
11
- name: "PlBlockPage"
12
- }, R = /* @__PURE__ */ u({
13
- ...$,
14
- props: {
15
- noBodyGutters: { type: Boolean },
16
- bodyLoading: {}
17
- },
18
- setup(a) {
19
- const p = m(), n = a, i = v(() => typeof n.bodyLoading == "string" ? { variant: n.bodyLoading, ...B.LOADING } : n.bodyLoading), r = (e) => {
20
- e.removeAttribute("title"), e.clientWidth < e.scrollWidth && e.setAttribute("title", e.innerText);
21
- }, _ = {
22
- mounted: r,
23
- updated: r
24
- };
25
- return (e, w) => (l(), o("div", {
26
- class: f(["pl-layout-component pl-block-page", { noBodyGutters: a.noBodyGutters }])
27
- }, [
28
- d(p).title ? (l(), o("div", T, [
29
- t("div", E, [
30
- c((l(), o("span", null, [
31
- s(e.$slots, "title")
32
- ])), [
33
- [_]
34
- ]),
35
- s(e.$slots, "after-title")
36
- ]),
37
- t("div", S, [
38
- t("div", {
39
- id: d(P),
40
- class: "pl-block-page__title__append__teleport"
41
- }, null, 8, A),
42
- s(e.$slots, "append")
43
- ])
44
- ])) : (l(), o("div", G)),
45
- t("div", N, [
46
- c(y(d(L), g(b(i.value)), null, 16), [
47
- [h, i.value]
48
- ]),
49
- t("div", {
50
- style: k({ display: i.value ? "none" : "contents" })
51
- }, [
52
- s(e.$slots, "default")
53
- ], 4)
54
- ])
55
- ], 2));
56
- }
57
- });
1
+ import o from "./PlBlockPage.vue2.js";
2
+ import s from "./PlBlockPage.vue3.js";
3
+ import t from "../../_virtual/_plugin-vue_export-helper.js";
4
+ const e = {
5
+ $style: s
6
+ }, m = /* @__PURE__ */ t(o, [["__cssModules", e]]);
58
7
  export {
59
- R as default
8
+ m as default
60
9
  };
61
10
  //# sourceMappingURL=PlBlockPage.vue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PlBlockPage.vue.js","sources":["../../../src/layout/PlBlockPage/PlBlockPage.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Root block page component */\nexport default {\n name: 'PlBlockPage',\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport { computed, useSlots } from 'vue';\nimport { PlBlockPageTitleTeleportId } from './PlBlockPageTitleTeleportId';\nimport './pl-block-page.scss';\nimport { PL_PLACEHOLDER_TEXTS, PlPlaceholder, type PlPlaceholderProps } from '../PlPlaceholder';\n\nconst slots = useSlots();\n\nconst props = defineProps<{\n /**\n * If `true` body gutters are removed\n */\n noBodyGutters?: boolean;\n /**\n * If defined, a loading overlay is displayed on the page body (over all default slot content)\n */\n bodyLoading?: PlPlaceholderProps['variant'] | PlPlaceholderProps;\n}>();\n\nconst loadingPlaceholder = computed<PlPlaceholderProps | undefined>(() => {\n if (typeof props.bodyLoading === 'string') {\n return { variant: props.bodyLoading, ...PL_PLACEHOLDER_TEXTS.LOADING };\n }\n return props.bodyLoading;\n});\n\nconst setTitleIfNeeded = (el: HTMLElement) => {\n el.removeAttribute('title');\n if (el.clientWidth < el.scrollWidth) {\n el.setAttribute('title', el.innerText);\n }\n};\n\nconst vTextOverflownTitle = {\n mounted: setTitleIfNeeded,\n updated: setTitleIfNeeded,\n};\n</script>\n\n<template>\n <div class=\"pl-layout-component pl-block-page\" :class=\"{ noBodyGutters }\">\n <div v-if=\"slots.title\" class=\"pl-block-page__title\">\n <div class=\"pl-block-page__title__default\">\n <span v-text-overflown-title><slot name=\"title\" /></span>\n <slot name=\"after-title\" />\n </div>\n <div class=\"pl-block-page__title__append\">\n <div\n :id=\"PlBlockPageTitleTeleportId\"\n class=\"pl-block-page__title__append__teleport\"\n />\n <slot name=\"append\" />\n </div>\n </div>\n <div v-else />\n <div class=\"pl-block-page__body\">\n <PlPlaceholder v-show=\"loadingPlaceholder\" v-bind=\"loadingPlaceholder\" />\n <div :style=\"{ display: loadingPlaceholder ? 'none' : 'contents' }\">\n <slot />\n </div>\n </div>\n </div>\n</template>\n"],"names":["__default__","slots","useSlots","props","__props","loadingPlaceholder","computed","PL_PLACEHOLDER_TEXTS","setTitleIfNeeded","el","vTextOverflownTitle","_createElementBlock","_normalizeClass","_unref","_openBlock","_hoisted_1","_createElementVNode","_hoisted_2","_renderSlot","_ctx","_hoisted_3","PlBlockPageTitleTeleportId","_hoisted_5","_hoisted_6","_withDirectives","_createVNode"],"mappings":";;;;;;;;oKAEAA,IAAe;AAAA,EACb,MAAM;AACR;;;;;;;AASA,UAAMC,IAAQC,EAAA,GAERC,IAAQC,GAWRC,IAAqBC,EAAyC,MAC9D,OAAOH,EAAM,eAAgB,WACxB,EAAE,SAASA,EAAM,aAAa,GAAGI,EAAqB,QAAA,IAExDJ,EAAM,WACd,GAEKK,IAAmB,CAACC,MAAoB;AAC5C,MAAAA,EAAG,gBAAgB,OAAO,GACtBA,EAAG,cAAcA,EAAG,eACtBA,EAAG,aAAa,SAASA,EAAG,SAAS;AAAA,IAEzC,GAEMC,IAAsB;AAAA,MAC1B,SAASF;AAAA,MACT,SAASA;AAAA,IAAA;2BAKTG,EAqBM,OAAA;AAAA,MArBD,OAAKC,EAAA,CAAC,qCAAmC,EAAA,eAAWR,EAAA,eAAa,CAAA;AAAA,IAAA;MACzDS,EAAAZ,CAAA,EAAM,SAAjBa,KAAAH,EAYM,OAZNI,GAYM;AAAA,QAXJC,EAGM,OAHNC,GAGM;AAAA,kBAFJN,EAAyD,QAAA,MAAA;AAAA,YAA5BO,EAAqBC,EAAA,QAAA,OAAA;AAAA,UAAA;;;UAClDD,EAA2BC,EAAA,QAAA,aAAA;AAAA,QAAA;QAE7BH,EAMM,OANNI,GAMM;AAAA,UALJJ,EAGE,OAAA;AAAA,YAFC,IAAIH,EAAAQ,CAAA;AAAA,YACL,OAAM;AAAA,UAAA;UAERH,EAAsBC,EAAA,QAAA,QAAA;AAAA,QAAA;kBAG1BR,EAAc,OAAAW,CAAA;AAAA,MACdN,EAKM,OALNO,GAKM;AAAA,QAJJC,EAAAC,EAAyEZ,UAAtBR,EAAA,KAAkB,CAAA,GAAA,MAAA,EAAA,GAAA;AAAA,cAA9CA,EAAA,KAAkB;AAAA,QAAA;QACzCW,EAEM,OAAA;AAAA,UAFA,oBAAkBX,EAAA,QAAkB,SAAA,YAAA;AAAA,QAAA;UACxCa,EAAQC,EAAA,QAAA,SAAA;AAAA,QAAA;;;;;"}
1
+ {"version":3,"file":"PlBlockPage.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -1,5 +1,90 @@
1
- import f from "./PlBlockPage.vue.js";
1
+ (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode(".pl-block-page{--pl-block-page-body-padding: var(--main-spacing, 24px);background-color:var(--bg-elevated-01);height:100%;max-width:100%;display:grid;grid-template-rows:auto minmax(0,1fr)}.pl-block-page.noBodyGutters{--pl-block-page-body-padding: 0}.pl-block-page__title{display:flex;align-items:center;gap:12px;min-width:0;max-width:100%}.pl-block-page__title__default{flex:1;min-width:0;max-width:100%;margin:0;color:var(--txt-01);display:flex;flex-direction:row;align-items:center;gap:12px}.pl-block-page__title__default>span{font-size:28px;font-weight:500;line-height:36px;letter-spacing:-.56px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;max-width:100%;display:inline-block}.pl-block-page__title__append{margin-left:auto;display:flex;align-items:center;gap:2px}.pl-block-page__title__append__teleport{display:contents}.pl-block-page__body{max-width:100%;display:flex;flex-direction:column;gap:var(--gap-v);padding:var(--pl-block-page-body-padding);--thumb-color: var(--ic-02);overflow-y:auto;overflow-x:auto}.pl-block-page__body::-webkit-scrollbar{width:var(--scrollbar-width, 6px);height:5px;background-color:transparent;display:block}.pl-block-page__body::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.pl-block-page__body::-webkit-scrollbar-thumb:hover{--thumb-color: var(--border-color-focus)}")),document.head.appendChild(e)}}catch(l){console.error("vite-plugin-css-injected-by-js",l)}})();
2
+ import { defineComponent as g, mergeModels as b, useSlots as h, useModel as k, useCssModule as P, computed as T, useTemplateRef as B, watchEffect as L, createElementBlock as o, openBlock as s, normalizeClass as i, createElementVNode as t, unref as l, createCommentVNode as E, renderSlot as r, toDisplayString as M, withDirectives as v, createVNode as y, vModelText as S, normalizeProps as C, guardReactiveProps as z, vShow as D, normalizeStyle as G } from "vue";
3
+ import { PlBlockPageTitleTeleportTarget as N } from "./PlBlockPageTitleTeleportTarget.js";
4
+
5
+ import V from "../../components/PlIcon24/PlIcon24.vue.js";
6
+ import { PL_PLACEHOLDER_TEXTS as $ } from "../PlPlaceholder/index.js";
7
+ import w from "../PlPlaceholder/PlPlaceholder.vue.js";
8
+ const I = { class: "pl-block-page__title" }, R = { class: "pl-block-page__title__default" }, A = { key: 0 }, O = { key: 1 }, H = { class: "pl-block-page__title__append" }, U = ["placeholder"], X = { key: 1 }, j = { class: "pl-block-page__body" }, q = {
9
+ name: "PlBlockPage"
10
+ }, Z = /* @__PURE__ */ g({
11
+ ...q,
12
+ props: /* @__PURE__ */ b({
13
+ title: {},
14
+ subtitlePlaceholder: {},
15
+ noBodyGutters: { type: Boolean },
16
+ bodyLoading: {}
17
+ }, {
18
+ subtitle: {},
19
+ subtitleModifiers: {}
20
+ }),
21
+ emits: ["update:subtitle"],
22
+ setup(p) {
23
+ const u = h(), e = p, n = k(p, "subtitle"), d = P(), c = T(() => typeof e.bodyLoading == "string" ? { variant: e.bodyLoading, ...$.LOADING } : e.bodyLoading), _ = B("teleportTarget");
24
+ return L(() => {
25
+ N.value = _.value;
26
+ }), (a, m) => (s(), o("div", {
27
+ class: i(["pl-layout-component pl-block-page", { noBodyGutters: e.noBodyGutters }])
28
+ }, [
29
+ l(u).title || e.title ? (s(), o("div", {
30
+ key: 0,
31
+ class: i(l(d).header)
32
+ }, [
33
+ t("div", I, [
34
+ t("div", R, [
35
+ l(u).title ? (s(), o("span", A, [
36
+ r(a.$slots, "title")
37
+ ])) : (s(), o("span", O, M(e.title), 1)),
38
+ r(a.$slots, "after-title")
39
+ ]),
40
+ t("div", H, [
41
+ t("div", {
42
+ ref_key: "teleportTarget",
43
+ ref: _,
44
+ class: "pl-block-page__title__append__teleport"
45
+ }, null, 512),
46
+ r(a.$slots, "append")
47
+ ])
48
+ ]),
49
+ n.value !== void 0 ? (s(), o("div", {
50
+ key: 0,
51
+ class: i(l(d).subtitle)
52
+ }, [
53
+ v(t("input", {
54
+ "onUpdate:modelValue": m[0] || (m[0] = (f) => n.value = f),
55
+ placeholder: e.subtitlePlaceholder
56
+ }, null, 8, U), [
57
+ [
58
+ S,
59
+ n.value,
60
+ void 0,
61
+ {
62
+ lazy: !0,
63
+ trim: !0
64
+ }
65
+ ]
66
+ ]),
67
+ y(l(V), {
68
+ class: i(l(d).editIcon),
69
+ name: "edit",
70
+ color: "var(--ic-02)"
71
+ }, null, 8, ["class"])
72
+ ], 2)) : E("", !0)
73
+ ], 2)) : (s(), o("div", X)),
74
+ t("div", j, [
75
+ v(y(l(w), C(z(c.value)), null, 16), [
76
+ [D, c.value]
77
+ ]),
78
+ t("div", {
79
+ style: G({ display: c.value ? "none" : "contents" })
80
+ }, [
81
+ r(a.$slots, "default")
82
+ ], 4)
83
+ ])
84
+ ], 2));
85
+ }
86
+ });
2
87
  export {
3
- f as default
88
+ Z as default
4
89
  };
5
90
  //# sourceMappingURL=PlBlockPage.vue2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PlBlockPage.vue2.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"PlBlockPage.vue2.js","sources":["../../../src/layout/PlBlockPage/PlBlockPage.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Root block page component */\nexport default {\n name: 'PlBlockPage',\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport { computed, useCssModule, useSlots, useTemplateRef, watchEffect } from 'vue';\nimport { PlBlockPageTitleTeleportTarget } from './PlBlockPageTitleTeleportTarget';\nimport './pl-block-page.scss';\nimport { PlIcon24 } from '../../components/PlIcon24';\nimport { type PlPlaceholderProps, PL_PLACEHOLDER_TEXTS, PlPlaceholder } from '../PlPlaceholder';\n\nconst slots = useSlots();\n\nconst props = defineProps<{\n /**\n * Page title (won't be displayed if `title` slot is also provided)\n */\n title?: string;\n /**\n * Text to display when subtitle is empty\n */\n subtitlePlaceholder?: string;\n /**\n * If `true` body gutters are removed\n */\n noBodyGutters?: boolean;\n /**\n * If defined, a loading overlay is displayed on the page body (over all default slot content)\n */\n bodyLoading?: PlPlaceholderProps['variant'] | PlPlaceholderProps;\n}>();\n\n/** Page subtitle (editable) */\nconst subtitle = defineModel<string>('subtitle');\n\nconst styles = useCssModule();\n\nconst loadingPlaceholder = computed<PlPlaceholderProps | undefined>(() => {\n if (typeof props.bodyLoading === 'string') {\n return { variant: props.bodyLoading, ...PL_PLACEHOLDER_TEXTS.LOADING };\n }\n return props.bodyLoading;\n});\n\nconst teleportTarget = useTemplateRef('teleportTarget');\n\nwatchEffect(() => {\n PlBlockPageTitleTeleportTarget.value = teleportTarget.value;\n});\n</script>\n\n<template>\n <div class=\"pl-layout-component pl-block-page\" :class=\"{ noBodyGutters: props.noBodyGutters }\">\n <div v-if=\"slots.title || props.title\" :class=\"styles.header\">\n <div class=\"pl-block-page__title\">\n <div class=\"pl-block-page__title__default\">\n <span v-if=\"slots.title\"><slot name=\"title\" /></span>\n <span v-else>{{ props.title }}</span>\n <slot name=\"after-title\" />\n </div>\n <div class=\"pl-block-page__title__append\">\n <div\n ref=\"teleportTarget\"\n class=\"pl-block-page__title__append__teleport\"\n />\n <slot name=\"append\" />\n </div>\n </div>\n <div v-if=\"subtitle !== undefined\" :class=\"styles.subtitle\">\n <input\n v-model.lazy.trim=\"subtitle\"\n :placeholder=\"props.subtitlePlaceholder\"\n />\n <PlIcon24 :class=\"styles.editIcon\" name=\"edit\" color=\"var(--ic-02)\" />\n </div>\n </div>\n <div v-else />\n <div class=\"pl-block-page__body\">\n <PlPlaceholder v-show=\"loadingPlaceholder\" v-bind=\"loadingPlaceholder\" />\n <div :style=\"{ display: loadingPlaceholder ? 'none' : 'contents' }\">\n <slot />\n </div>\n </div>\n </div>\n</template>\n\n<style module>\n.header {\n display: flex;\n flex-direction: column;\n padding: 12px 24px;\n margin-block-end: -8px;\n gap: 2px;\n overflow: hidden;\n}\n\n.subtitle {\n display: flex;\n padding-inline-end: 28px;\n\n input {\n anchor-name: --pl-block-page-subtitle;\n field-sizing: content;\n padding: 0;\n border: none;\n outline: none;\n caret-color: var(--border-color-focus);\n color: var(--txt-01);\n font-family: Manrope;\n font-size: 20px;\n font-weight: 500;\n line-height: 28px;\n letter-spacing: -0.2px;\n margin-block-end: -4px;\n max-inline-size: 100%;\n text-overflow: ellipsis;\n\n &::placeholder {\n color: var(--txt-03);\n }\n }\n\n .editIcon {\n visibility: hidden;\n position: fixed;\n position-anchor: --pl-block-page-subtitle;\n position-area: center inline-end;\n inset-inline-start: 4px;\n }\n &:hover, &:focus-within {\n .editIcon {\n visibility: visible;\n }\n }\n}\n</style>\n"],"names":["__default__","slots","useSlots","props","__props","subtitle","_useModel","styles","useCssModule","loadingPlaceholder","computed","PL_PLACEHOLDER_TEXTS","teleportTarget","useTemplateRef","watchEffect","PlBlockPageTitleTeleportTarget","_createElementBlock","_normalizeClass","_unref","_createElementVNode","_hoisted_1","_hoisted_2","_hoisted_3","_renderSlot","_ctx","_hoisted_4","_toDisplayString","_hoisted_5","$event","_createVNode","PlIcon24","_hoisted_7","_hoisted_8","_withDirectives"],"mappings":";;;;;;uPAEAA,IAAe;AAAA,EACb,MAAM;AACR;;;;;;;;;;;;;AAUA,UAAMC,IAAQC,EAAA,GAERC,IAAQC,GAoBRC,IAAWC,KAAoB,UAAU,GAEzCC,IAASC,EAAA,GAETC,IAAqBC,EAAyC,MAC9D,OAAOP,EAAM,eAAgB,WACxB,EAAE,SAASA,EAAM,aAAa,GAAGQ,EAAqB,QAAA,IAExDR,EAAM,WACd,GAEKS,IAAiBC,EAAe,gBAAgB;AAEtD,WAAAC,EAAY,MAAM;AAChB,MAAAC,EAA+B,QAAQH,EAAe;AAAA,IACxD,CAAC,mBAICI,EA+BM,OAAA;AAAA,MA/BD,OAAKC,EAAA,CAAC,qCAAmC,EAAA,eAA0Bd,EAAM,eAAa,CAAA;AAAA,IAAA;MAC9Ee,EAAAjB,CAAA,EAAM,SAASE,EAAM,cAAhCa,EAsBM,OAAA;AAAA;QAtBkC,OAAKC,EAAEC,EAAAX,CAAA,EAAO,MAAM;AAAA,MAAA;QAC1DY,EAaM,OAbNC,GAaM;AAAA,UAZJD,EAIM,OAJNE,GAIM;AAAA,YAHQH,EAAAjB,CAAA,EAAM,cAAlBe,EAAqD,QAAAM,GAAA;AAAA,cAA5BC,EAAqBC,EAAA,QAAA,OAAA;AAAA,YAAA,YAC9CR,EAAqC,QAAAS,GAAAC,EAArBvB,EAAM,KAAK,GAAA,CAAA;AAAA,YAC3BoB,EAA2BC,EAAA,QAAA,aAAA;AAAA,UAAA;UAE7BL,EAMM,OANNQ,GAMM;AAAA,YALJR,EAGE,OAAA;AAAA,uBAFI;AAAA,cAAJ,KAAIP;AAAA,cACJ,OAAM;AAAA,YAAA;YAERW,EAAsBC,EAAA,QAAA,QAAA;AAAA,UAAA;;QAGfnB,EAAA,UAAa,eAAxBW,EAMM,OAAA;AAAA;UAN8B,OAAKC,EAAEC,EAAAX,CAAA,EAAO,QAAQ;AAAA,QAAA;YACxDY,EAGE,SAAA;AAAA,0DAFmBd,EAAQ,QAAAuB;AAAA,YAC1B,aAAazB,EAAM;AAAA,UAAA;;;cADDE,EAAA;AAAA;;gBAAX,MAAR;AAAA,gBAAa,MAAb;AAAA,cAAA;AAAA;;UAGFwB,EAAsEX,EAAAY,CAAA,GAAA;AAAA,YAA3D,OAAKb,EAAEC,EAAAX,CAAA,EAAO,QAAQ;AAAA,YAAE,MAAK;AAAA,YAAO,OAAM;AAAA,UAAA;;qBAGzDS,EAAc,OAAAe,CAAA;AAAA,MACdZ,EAKM,OALNa,GAKM;AAAA,QAJJC,EAAAJ,EAAyEX,UAAtBT,EAAA,KAAkB,CAAA,GAAA,MAAA,EAAA,GAAA;AAAA,cAA9CA,EAAA,KAAkB;AAAA,QAAA;QACzCU,EAEM,OAAA;AAAA,UAFA,oBAAkBV,EAAA,QAAkB,SAAA,YAAA;AAAA,QAAA;UACxCc,EAAQC,EAAA,QAAA,SAAA;AAAA,QAAA;;;;;"}
@@ -0,0 +1,13 @@
1
+ (function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode("._header_y99r6_2{display:flex;flex-direction:column;padding:12px 24px;margin-block-end:-8px;gap:2px;overflow:hidden}._subtitle_y99r6_11{display:flex;padding-inline-end:28px}._subtitle_y99r6_11 input{anchor-name:--pl-block-page-subtitle;field-sizing:content;padding:0;border:none;outline:none;caret-color:var(--border-color-focus);color:var(--txt-01);font-family:Manrope;font-size:20px;font-weight:500;line-height:28px;letter-spacing:-.2px;margin-block-end:-4px;max-inline-size:100%;text-overflow:ellipsis}._subtitle_y99r6_11 input::placeholder{color:var(--txt-03)}._subtitle_y99r6_11 ._editIcon_y99r6_37{visibility:hidden;position:fixed;position-anchor:--pl-block-page-subtitle;position-area:center inline-end;inset-inline-start:4px}._subtitle_y99r6_11:hover ._editIcon_y99r6_37,._subtitle_y99r6_11:focus-within ._editIcon_y99r6_37{visibility:visible}")),document.head.appendChild(e)}}catch(i){console.error("vite-plugin-css-injected-by-js",i)}})();
2
+ const t = "_header_y99r6_2", e = "_subtitle_y99r6_11", s = "_editIcon_y99r6_37", _ = {
3
+ header: t,
4
+ subtitle: e,
5
+ editIcon: s
6
+ };
7
+ export {
8
+ _ as default,
9
+ s as editIcon,
10
+ t as header,
11
+ e as subtitle
12
+ };
13
+ //# sourceMappingURL=PlBlockPage.vue3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlBlockPage.vue3.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
@@ -0,0 +1,2 @@
1
+ export declare const PlBlockPageTitleTeleportTarget: import('vue').Ref<HTMLElement | null | undefined, HTMLElement | null | undefined>;
2
+ //# sourceMappingURL=PlBlockPageTitleTeleportTarget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlBlockPageTitleTeleportTarget.d.ts","sourceRoot":"","sources":["../../../src/layout/PlBlockPage/PlBlockPageTitleTeleportTarget.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,8BAA8B,mFAA4B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { ref as e } from "vue";
2
+ const r = e();
3
+ export {
4
+ r as PlBlockPageTitleTeleportTarget
5
+ };
6
+ //# sourceMappingURL=PlBlockPageTitleTeleportTarget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlBlockPageTitleTeleportTarget.js","sources":["../../../src/layout/PlBlockPage/PlBlockPageTitleTeleportTarget.ts"],"sourcesContent":["import { ref } from 'vue';\n\nexport const PlBlockPageTitleTeleportTarget = ref<HTMLElement | null>();\n"],"names":["PlBlockPageTitleTeleportTarget","ref"],"mappings":";AAEO,MAAMA,IAAiCC,EAAA;"}
@@ -1,2 +1,2 @@
1
- export declare function usePlBlockPageTitleTeleportTarget(componentName: string): import('vue').Ref<string | undefined, string | undefined>;
1
+ export declare function usePlBlockPageTitleTeleportTarget(componentName: string): import('vue').Ref<HTMLElement | null | undefined, HTMLElement | null | undefined>;
2
2
  //# sourceMappingURL=usePlBlockPageTitleTeleportTarget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePlBlockPageTitleTeleportTarget.d.ts","sourceRoot":"","sources":["../../../src/layout/PlBlockPage/usePlBlockPageTitleTeleportTarget.ts"],"names":[],"mappings":"AAKA,wBAAgB,iCAAiC,CAAC,aAAa,EAAE,MAAM,6DAmBtE"}
1
+ {"version":3,"file":"usePlBlockPageTitleTeleportTarget.d.ts","sourceRoot":"","sources":["../../../src/layout/PlBlockPage/usePlBlockPageTitleTeleportTarget.ts"],"names":[],"mappings":"AAGA,wBAAgB,iCAAiC,CAAC,aAAa,EAAE,MAAM,qFAgBtE"}
@@ -1,18 +1,17 @@
1
- import { ref as n, onMounted as c, onUpdated as l, nextTick as i } from "vue";
2
- import { PlBlockPageTitleTeleportId as s } from "./PlBlockPageTitleTeleportId.js";
3
- const t = "#" + s;
4
- function p(r) {
5
- const e = n(), o = () => {
6
- i(() => {
7
- e.value = document.querySelector(t) ? t : void 0, e.value || console.error(
8
- `[${r}] Error: 'PlBlockPage' component is missing.
9
- Ensure that you placed the components inside <PlBlockPage />.`
1
+ import { onMounted as r, onUpdated as i, nextTick as l } from "vue";
2
+ import { PlBlockPageTitleTeleportTarget as o } from "./PlBlockPageTitleTeleportTarget.js";
3
+ function a(t) {
4
+ const e = () => {
5
+ l(() => {
6
+ o.value || console.error(
7
+ `[${t}] Error: Either 'PlBlockPage' component is missing or it has no title.
8
+ Ensure that you placed the components inside <PlBlockPage /> with a title.`
10
9
  );
11
10
  });
12
11
  };
13
- return c(o), l(o), e;
12
+ return r(e), i(e), o;
14
13
  }
15
14
  export {
16
- p as usePlBlockPageTitleTeleportTarget
15
+ a as usePlBlockPageTitleTeleportTarget
17
16
  };
18
17
  //# sourceMappingURL=usePlBlockPageTitleTeleportTarget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePlBlockPageTitleTeleportTarget.js","sources":["../../../src/layout/PlBlockPage/usePlBlockPageTitleTeleportTarget.ts"],"sourcesContent":["import { nextTick, onMounted, onUpdated, ref } from 'vue';\nimport { PlBlockPageTitleTeleportId } from './PlBlockPageTitleTeleportId';\n\nconst selector = '#' + PlBlockPageTitleTeleportId;\n\nexport function usePlBlockPageTitleTeleportTarget(componentName: string) {\n const target = ref<string>();\n\n const check = () => {\n nextTick(() => {\n target.value = document.querySelector(selector) ? selector : undefined;\n if (!target.value) {\n console.error(\n `[${componentName}] Error: 'PlBlockPage' component is missing. \n Ensure that you placed the components inside <PlBlockPage />.`,\n );\n }\n });\n };\n\n onMounted(check);\n onUpdated(check);\n\n return target;\n}\n"],"names":["selector","PlBlockPageTitleTeleportId","usePlBlockPageTitleTeleportTarget","componentName","target","ref","check","nextTick","onMounted","onUpdated"],"mappings":";;AAGA,MAAMA,IAAW,MAAMC;AAEhB,SAASC,EAAkCC,GAAuB;AACvE,QAAMC,IAASC,EAAA,GAETC,IAAQ,MAAM;AAClB,IAAAC,EAAS,MAAM;AACb,MAAAH,EAAO,QAAQ,SAAS,cAAcJ,CAAQ,IAAIA,IAAW,QACxDI,EAAO,SACV,QAAQ;AAAA,QACN,IAAID,CAAa;AAAA;AAAA,MAAA;AAAA,IAIvB,CAAC;AAAA,EACH;AAEA,SAAAK,EAAUF,CAAK,GACfG,EAAUH,CAAK,GAERF;AACT;"}
1
+ {"version":3,"file":"usePlBlockPageTitleTeleportTarget.js","sources":["../../../src/layout/PlBlockPage/usePlBlockPageTitleTeleportTarget.ts"],"sourcesContent":["import { nextTick, onMounted, onUpdated } from 'vue';\nimport { PlBlockPageTitleTeleportTarget } from './PlBlockPageTitleTeleportTarget';\n\nexport function usePlBlockPageTitleTeleportTarget(componentName: string) {\n const check = () => {\n nextTick(() => {\n if (!PlBlockPageTitleTeleportTarget.value) {\n console.error(\n `[${componentName}] Error: Either 'PlBlockPage' component is missing or it has no title. \n Ensure that you placed the components inside <PlBlockPage /> with a title.`,\n );\n }\n });\n };\n\n onMounted(check);\n onUpdated(check);\n\n return PlBlockPageTitleTeleportTarget;\n}\n"],"names":["usePlBlockPageTitleTeleportTarget","componentName","check","nextTick","PlBlockPageTitleTeleportTarget","onMounted","onUpdated"],"mappings":";;AAGO,SAASA,EAAkCC,GAAuB;AACvE,QAAMC,IAAQ,MAAM;AAClB,IAAAC,EAAS,MAAM;AACb,MAAKC,EAA+B,SAClC,QAAQ;AAAA,QACN,IAAIH,CAAa;AAAA;AAAA,MAAA;AAAA,IAIvB,CAAC;AAAA,EACH;AAEA,SAAAI,EAAUH,CAAK,GACfI,EAAUJ,CAAK,GAERE;AACT;"}
@@ -1,5 +1,5 @@
1
1
  (function(){"use strict";try{if(typeof document<"u"){var o=document.createElement("style");o.appendChild(document.createTextNode(".double-contour.top>div{border-bottom-right-radius:0;border-bottom-left-radius:0}.double-contour.bottom>div{border-top-right-radius:0;border-top-left-radius:0}.double-contour.left>div{border-top-right-radius:0;border-bottom-right-radius:0}.double-contour.right>div{border-top-left-radius:0;border-bottom-left-radius:0}.double-contour.top-left>div{border-top-right-radius:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.double-contour.top-right>div{border-bottom-right-radius:0;border-top-left-radius:0;border-top-right-radius:0}.double-contour.bottom-left>div{border-top-right-radius:0;border-bottom-right-radius:0;border-top-left-radius:0}.double-contour.bottom-right>div{border-top-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:0}.double-contour.middle>div{border-radius:0}")),document.head.appendChild(o)}}catch(r){console.error("vite-plugin-css-injected-by-js",r)}})();
2
- import o from "./DoubleContour.vue2.js";
2
+ import o from "./DoubleContour.vue.js";
3
3
 
4
4
  export {
5
5
  o as default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/uikit",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -32,8 +32,8 @@
32
32
  "d3-axis": "^3.0.0",
33
33
  "resize-observer-polyfill": "^1.5.1",
34
34
  "canonicalize": "~2.1.0",
35
- "@platforma-sdk/model": "1.50.0",
36
- "@milaboratories/helpers": "1.13.0"
35
+ "@milaboratories/helpers": "1.13.0",
36
+ "@platforma-sdk/model": "1.51.2"
37
37
  },
38
38
  "devDependencies": {
39
39
  "jsdom": "^25.0.1",
@@ -43,10 +43,10 @@
43
43
  "yarpm": "^1.2.0",
44
44
  "svgo": "^3.3.2",
45
45
  "typescript": "~5.6.3",
46
- "@milaboratories/eslint-config": "1.0.5",
47
- "@milaboratories/ts-configs": "1.2.0",
48
46
  "@milaboratories/build-configs": "1.2.1",
49
- "@milaboratories/ts-builder": "1.2.1"
47
+ "@milaboratories/eslint-config": "1.0.5",
48
+ "@milaboratories/ts-builder": "1.2.1",
49
+ "@milaboratories/ts-configs": "1.2.0"
50
50
  },
51
51
  "scripts": {
52
52
  "dev": "ts-builder serve --target browser-lib --build-config ./build.browser-lib.config.js",
@@ -6,14 +6,23 @@ export default {
6
6
  </script>
7
7
 
8
8
  <script lang="ts" setup>
9
- import { computed, useSlots } from 'vue';
10
- import { PlBlockPageTitleTeleportId } from './PlBlockPageTitleTeleportId';
9
+ import { computed, useCssModule, useSlots, useTemplateRef, watchEffect } from 'vue';
10
+ import { PlBlockPageTitleTeleportTarget } from './PlBlockPageTitleTeleportTarget';
11
11
  import './pl-block-page.scss';
12
- import { PL_PLACEHOLDER_TEXTS, PlPlaceholder, type PlPlaceholderProps } from '../PlPlaceholder';
12
+ import { PlIcon24 } from '../../components/PlIcon24';
13
+ import { type PlPlaceholderProps, PL_PLACEHOLDER_TEXTS, PlPlaceholder } from '../PlPlaceholder';
13
14
 
14
15
  const slots = useSlots();
15
16
 
16
17
  const props = defineProps<{
18
+ /**
19
+ * Page title (won't be displayed if `title` slot is also provided)
20
+ */
21
+ title?: string;
22
+ /**
23
+ * Text to display when subtitle is empty
24
+ */
25
+ subtitlePlaceholder?: string;
17
26
  /**
18
27
  * If `true` body gutters are removed
19
28
  */
@@ -24,6 +33,11 @@ const props = defineProps<{
24
33
  bodyLoading?: PlPlaceholderProps['variant'] | PlPlaceholderProps;
25
34
  }>();
26
35
 
36
+ /** Page subtitle (editable) */
37
+ const subtitle = defineModel<string>('subtitle');
38
+
39
+ const styles = useCssModule();
40
+
27
41
  const loadingPlaceholder = computed<PlPlaceholderProps | undefined>(() => {
28
42
  if (typeof props.bodyLoading === 'string') {
29
43
  return { variant: props.bodyLoading, ...PL_PLACEHOLDER_TEXTS.LOADING };
@@ -31,32 +45,36 @@ const loadingPlaceholder = computed<PlPlaceholderProps | undefined>(() => {
31
45
  return props.bodyLoading;
32
46
  });
33
47
 
34
- const setTitleIfNeeded = (el: HTMLElement) => {
35
- el.removeAttribute('title');
36
- if (el.clientWidth < el.scrollWidth) {
37
- el.setAttribute('title', el.innerText);
38
- }
39
- };
48
+ const teleportTarget = useTemplateRef('teleportTarget');
40
49
 
41
- const vTextOverflownTitle = {
42
- mounted: setTitleIfNeeded,
43
- updated: setTitleIfNeeded,
44
- };
50
+ watchEffect(() => {
51
+ PlBlockPageTitleTeleportTarget.value = teleportTarget.value;
52
+ });
45
53
  </script>
46
54
 
47
55
  <template>
48
- <div class="pl-layout-component pl-block-page" :class="{ noBodyGutters }">
49
- <div v-if="slots.title" class="pl-block-page__title">
50
- <div class="pl-block-page__title__default">
51
- <span v-text-overflown-title><slot name="title" /></span>
52
- <slot name="after-title" />
56
+ <div class="pl-layout-component pl-block-page" :class="{ noBodyGutters: props.noBodyGutters }">
57
+ <div v-if="slots.title || props.title" :class="styles.header">
58
+ <div class="pl-block-page__title">
59
+ <div class="pl-block-page__title__default">
60
+ <span v-if="slots.title"><slot name="title" /></span>
61
+ <span v-else>{{ props.title }}</span>
62
+ <slot name="after-title" />
63
+ </div>
64
+ <div class="pl-block-page__title__append">
65
+ <div
66
+ ref="teleportTarget"
67
+ class="pl-block-page__title__append__teleport"
68
+ />
69
+ <slot name="append" />
70
+ </div>
53
71
  </div>
54
- <div class="pl-block-page__title__append">
55
- <div
56
- :id="PlBlockPageTitleTeleportId"
57
- class="pl-block-page__title__append__teleport"
72
+ <div v-if="subtitle !== undefined" :class="styles.subtitle">
73
+ <input
74
+ v-model.lazy.trim="subtitle"
75
+ :placeholder="props.subtitlePlaceholder"
58
76
  />
59
- <slot name="append" />
77
+ <PlIcon24 :class="styles.editIcon" name="edit" color="var(--ic-02)" />
60
78
  </div>
61
79
  </div>
62
80
  <div v-else />
@@ -68,3 +86,54 @@ const vTextOverflownTitle = {
68
86
  </div>
69
87
  </div>
70
88
  </template>
89
+
90
+ <style module>
91
+ .header {
92
+ display: flex;
93
+ flex-direction: column;
94
+ padding: 12px 24px;
95
+ margin-block-end: -8px;
96
+ gap: 2px;
97
+ overflow: hidden;
98
+ }
99
+
100
+ .subtitle {
101
+ display: flex;
102
+ padding-inline-end: 28px;
103
+
104
+ input {
105
+ anchor-name: --pl-block-page-subtitle;
106
+ field-sizing: content;
107
+ padding: 0;
108
+ border: none;
109
+ outline: none;
110
+ caret-color: var(--border-color-focus);
111
+ color: var(--txt-01);
112
+ font-family: Manrope;
113
+ font-size: 20px;
114
+ font-weight: 500;
115
+ line-height: 28px;
116
+ letter-spacing: -0.2px;
117
+ margin-block-end: -4px;
118
+ max-inline-size: 100%;
119
+ text-overflow: ellipsis;
120
+
121
+ &::placeholder {
122
+ color: var(--txt-03);
123
+ }
124
+ }
125
+
126
+ .editIcon {
127
+ visibility: hidden;
128
+ position: fixed;
129
+ position-anchor: --pl-block-page-subtitle;
130
+ position-area: center inline-end;
131
+ inset-inline-start: 4px;
132
+ }
133
+ &:hover, &:focus-within {
134
+ .editIcon {
135
+ visibility: visible;
136
+ }
137
+ }
138
+ }
139
+ </style>
@@ -0,0 +1,3 @@
1
+ import { ref } from 'vue';
2
+
3
+ export const PlBlockPageTitleTeleportTarget = ref<HTMLElement | null>();
@@ -1,9 +1,8 @@
1
- @use "../../assets/mixins.scss" as *;
1
+ @use '../../assets/mixins.scss' as *;
2
2
 
3
3
  .pl-block-page {
4
4
  --pl-block-page-body-padding: var(--main-spacing, 24px);
5
5
 
6
- padding: var(--container-spacing);
7
6
  background-color: var(--bg-elevated-01);
8
7
  height: 100%;
9
8
  max-width: 100%;
@@ -15,11 +14,9 @@
15
14
  }
16
15
 
17
16
  &__title {
18
- height: 80px;
19
17
  display: flex;
20
18
  align-items: center;
21
19
  gap: 12px;
22
- padding: 20px 24px;
23
20
  min-width: 0;
24
21
  max-width: 100%;
25
22
 
@@ -55,9 +52,7 @@
55
52
  gap: 2px;
56
53
 
57
54
  &__teleport {
58
- display: flex;
59
- align-items: center;
60
- gap: 2px;
55
+ display: contents;
61
56
  }
62
57
  }
63
58
  }
@@ -70,4 +65,4 @@
70
65
  padding: var(--pl-block-page-body-padding);
71
66
  @include scrollbar(true, true);
72
67
  }
73
- }
68
+ }
@@ -1,18 +1,13 @@
1
- import { nextTick, onMounted, onUpdated, ref } from 'vue';
2
- import { PlBlockPageTitleTeleportId } from './PlBlockPageTitleTeleportId';
3
-
4
- const selector = '#' + PlBlockPageTitleTeleportId;
1
+ import { nextTick, onMounted, onUpdated } from 'vue';
2
+ import { PlBlockPageTitleTeleportTarget } from './PlBlockPageTitleTeleportTarget';
5
3
 
6
4
  export function usePlBlockPageTitleTeleportTarget(componentName: string) {
7
- const target = ref<string>();
8
-
9
5
  const check = () => {
10
6
  nextTick(() => {
11
- target.value = document.querySelector(selector) ? selector : undefined;
12
- if (!target.value) {
7
+ if (!PlBlockPageTitleTeleportTarget.value) {
13
8
  console.error(
14
- `[${componentName}] Error: 'PlBlockPage' component is missing.
15
- Ensure that you placed the components inside <PlBlockPage />.`,
9
+ `[${componentName}] Error: Either 'PlBlockPage' component is missing or it has no title.
10
+ Ensure that you placed the components inside <PlBlockPage /> with a title.`,
16
11
  );
17
12
  }
18
13
  });
@@ -21,5 +16,5 @@ export function usePlBlockPageTitleTeleportTarget(componentName: string) {
21
16
  onMounted(check);
22
17
  onUpdated(check);
23
18
 
24
- return target;
19
+ return PlBlockPageTitleTeleportTarget;
25
20
  }