@masterteam/client-components 0.0.65 → 0.0.67
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/assets/client-components.css +1 -1
- package/fesm2022/masterteam-client-components-client-instance-preview.mjs +13 -0
- package/fesm2022/masterteam-client-components-client-instance-preview.mjs.map +1 -1
- package/fesm2022/masterteam-client-components-client-list.mjs +113 -6
- package/fesm2022/masterteam-client-components-client-list.mjs.map +1 -1
- package/package.json +3 -3
- package/types/masterteam-client-components-client-instance-preview.d.ts +7 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-200:oklch(88.5% .062 18.334);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-950:oklch(25.8% .092 26.042);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-900:oklch(21% .034 264.665);--spacing:.25rem;--container-md:28rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-semibold:600;--tracking-wide:.025em;--radius-lg:.5rem;--radius-xl:.75rem;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.end-2{inset-inline-end:calc(var(--spacing) * 2)}.top-2{top:calc(var(--spacing) * 2)}.z-10{z-index:10}.col-span-1{grid-column:span 1/span 1}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:0}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.ml-auto{margin-left:auto}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.min-h-\[20rem\]{min-height:20rem}.min-h-\[22rem\]{min-height:22rem}.min-h-\[420px\]{min-height:420px}.w-1{width:var(--spacing)}.w-28{width:calc(var(--spacing) * 28)}.w-40{width:calc(var(--spacing) * 40)}.w-full{width:100%}.max-w-md{max-width:var(--container-md)}.min-w-0{min-width:0}.min-w-44{min-width:calc(var(--spacing) * 44)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.animate-pulse{animation:var(--animate-pulse)}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-y{border-block-style:var(--tw-border-style);border-block-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-red-200{border-color:var(--color-red-200)}.border-surface-200{border-color:var(--p-surface-200)}@supports (color:color-mix(in lab, red, red)){.border-surface-200{border-color:color-mix(in srgb, var(--p-surface-200) calc(100% * 1), transparent)}}.border-surface-300{border-color:var(--p-surface-300)}@supports (color:color-mix(in lab, red, red)){.border-surface-300{border-color:color-mix(in srgb, var(--p-surface-300) calc(100% * 1), transparent)}}.bg-primary-50{background-color:var(--p-primary-50)}@supports (color:color-mix(in lab, red, red)){.bg-primary-50{background-color:color-mix(in srgb, var(--p-primary-50) calc(100% * 1), transparent)}}.bg-red-50{background-color:var(--color-red-50)}.bg-surface-50{background-color:var(--p-surface-50)}@supports (color:color-mix(in lab, red, red)){.bg-surface-50{background-color:color-mix(in srgb, var(--p-surface-50) calc(100% * 1), transparent)}}.bg-surface-200{background-color:var(--p-surface-200)}@supports (color:color-mix(in lab, red, red)){.bg-surface-200{background-color:color-mix(in srgb, var(--p-surface-200) calc(100% * 1), transparent)}}.p-1{padding:var(--spacing)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-start{text-align:start}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-700{color:var(--color-gray-700)}.text-gray-900{color:var(--color-gray-900)}.text-primary-700{color:var(--p-primary-700)}@supports (color:color-mix(in lab, red, red)){.text-primary-700{color:color-mix(in srgb, var(--p-primary-700) calc(100% * 1), transparent)}}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-surface-500{color:var(--p-surface-500)}@supports (color:color-mix(in lab, red, red)){.text-surface-500{color:color-mix(in srgb, var(--p-surface-500) calc(100% * 1), transparent)}}.uppercase{text-transform:uppercase}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}@media (min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}.dark\:border-surface-700:where(.dark,.dark *){border-color:var(--p-surface-700)}@supports (color:color-mix(in lab, red, red)){.dark\:border-surface-700:where(.dark,.dark *){border-color:color-mix(in srgb, var(--p-surface-700) calc(100% * 1), transparent)}}.dark\:bg-primary-950:where(.dark,.dark *){background-color:var(--p-primary-950)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-primary-950:where(.dark,.dark *){background-color:color-mix(in srgb, var(--p-primary-950) calc(100% * 1), transparent)}}.dark\:bg-surface-900:where(.dark,.dark *){background-color:var(--p-surface-900)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-surface-900:where(.dark,.dark *){background-color:color-mix(in srgb, var(--p-surface-900) calc(100% * 1), transparent)}}.dark\:text-gray-100:where(.dark,.dark *){color:var(--color-gray-100)}.dark\:text-gray-200:where(.dark,.dark *){color:var(--color-gray-200)}.dark\:text-gray-400:where(.dark,.dark *){color:var(--color-gray-400)}.dark\:text-primary-300:where(.dark,.dark *){color:var(--p-primary-300)}@supports (color:color-mix(in lab, red, red)){.dark\:text-primary-300:where(.dark,.dark *){color:color-mix(in srgb, var(--p-primary-300) calc(100% * 1), transparent)}}@media (hover:hover){.dark\:hover\:bg-red-950:where(.dark,.dark *):hover{background-color:var(--color-red-950)}.dark\:hover\:bg-surface-700:where(.dark,.dark *):hover{background-color:var(--p-surface-700)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-surface-700:where(.dark,.dark *):hover{background-color:color-mix(in srgb, var(--p-surface-700) calc(100% * 1), transparent)}}}}@keyframes enter{0%{opacity:var(--p-enter-opacity,1);transform:translate3d(var(--p-enter-translate-x,0), var(--p-enter-translate-y,0), 0) scale3d(var(--p-enter-scale,1), var(--p-enter-scale,1), var(--p-enter-scale,1)) rotate(var(--p-enter-rotate,0))}}@keyframes leave{to{opacity:var(--p-leave-opacity,1);transform:translate3d(var(--p-leave-translate-x,0), var(--p-leave-translate-y,0), 0) scale3d(var(--p-leave-scale,1), var(--p-leave-scale,1), var(--p-leave-scale,1)) rotate(var(--p-leave-rotate,0))}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-200:oklch(88.5% .062 18.334);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-950:oklch(25.8% .092 26.042);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-900:oklch(21% .034 264.665);--spacing:.25rem;--container-md:28rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-semibold:600;--tracking-wide:.025em;--radius-lg:.5rem;--radius-xl:.75rem;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.end-2{inset-inline-end:calc(var(--spacing) * 2)}.top-2{top:calc(var(--spacing) * 2)}.z-10{z-index:10}.col-span-1{grid-column:span 1/span 1}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:0}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.ml-auto{margin-left:auto}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-80{height:calc(var(--spacing) * 80)}.h-px{height:1px}.min-h-\[20rem\]{min-height:20rem}.min-h-\[22rem\]{min-height:22rem}.min-h-\[420px\]{min-height:420px}.w-1{width:var(--spacing)}.w-28{width:calc(var(--spacing) * 28)}.w-40{width:calc(var(--spacing) * 40)}.w-full{width:100%}.max-w-md{max-width:var(--container-md)}.min-w-0{min-width:0}.min-w-44{min-width:calc(var(--spacing) * 44)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.animate-pulse{animation:var(--animate-pulse)}.cursor-pointer{cursor:pointer}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-y{border-block-style:var(--tw-border-style);border-block-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-red-200{border-color:var(--color-red-200)}.border-surface-200{border-color:var(--p-surface-200)}@supports (color:color-mix(in lab, red, red)){.border-surface-200{border-color:color-mix(in srgb, var(--p-surface-200) calc(100% * 1), transparent)}}.border-surface-300{border-color:var(--p-surface-300)}@supports (color:color-mix(in lab, red, red)){.border-surface-300{border-color:color-mix(in srgb, var(--p-surface-300) calc(100% * 1), transparent)}}.bg-primary-50{background-color:var(--p-primary-50)}@supports (color:color-mix(in lab, red, red)){.bg-primary-50{background-color:color-mix(in srgb, var(--p-primary-50) calc(100% * 1), transparent)}}.bg-red-50{background-color:var(--color-red-50)}.bg-surface-50{background-color:var(--p-surface-50)}@supports (color:color-mix(in lab, red, red)){.bg-surface-50{background-color:color-mix(in srgb, var(--p-surface-50) calc(100% * 1), transparent)}}.bg-surface-200{background-color:var(--p-surface-200)}@supports (color:color-mix(in lab, red, red)){.bg-surface-200{background-color:color-mix(in srgb, var(--p-surface-200) calc(100% * 1), transparent)}}.p-1{padding:var(--spacing)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-2{padding-inline:calc(var(--spacing) * 2)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-start{text-align:start}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-700{color:var(--color-gray-700)}.text-gray-900{color:var(--color-gray-900)}.text-primary-700{color:var(--p-primary-700)}@supports (color:color-mix(in lab, red, red)){.text-primary-700{color:color-mix(in srgb, var(--p-primary-700) calc(100% * 1), transparent)}}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-surface-500{color:var(--p-surface-500)}@supports (color:color-mix(in lab, red, red)){.text-surface-500{color:color-mix(in srgb, var(--p-surface-500) calc(100% * 1), transparent)}}.uppercase{text-transform:uppercase}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-red-50:hover{background-color:var(--color-red-50)}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}}@media (min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}.dark\:border-surface-700:where(.dark,.dark *){border-color:var(--p-surface-700)}@supports (color:color-mix(in lab, red, red)){.dark\:border-surface-700:where(.dark,.dark *){border-color:color-mix(in srgb, var(--p-surface-700) calc(100% * 1), transparent)}}.dark\:bg-primary-950:where(.dark,.dark *){background-color:var(--p-primary-950)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-primary-950:where(.dark,.dark *){background-color:color-mix(in srgb, var(--p-primary-950) calc(100% * 1), transparent)}}.dark\:bg-surface-900:where(.dark,.dark *){background-color:var(--p-surface-900)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-surface-900:where(.dark,.dark *){background-color:color-mix(in srgb, var(--p-surface-900) calc(100% * 1), transparent)}}.dark\:text-gray-100:where(.dark,.dark *){color:var(--color-gray-100)}.dark\:text-gray-200:where(.dark,.dark *){color:var(--color-gray-200)}.dark\:text-gray-400:where(.dark,.dark *){color:var(--color-gray-400)}.dark\:text-primary-300:where(.dark,.dark *){color:var(--p-primary-300)}@supports (color:color-mix(in lab, red, red)){.dark\:text-primary-300:where(.dark,.dark *){color:color-mix(in srgb, var(--p-primary-300) calc(100% * 1), transparent)}}@media (hover:hover){.dark\:hover\:bg-red-950:where(.dark,.dark *):hover{background-color:var(--color-red-950)}.dark\:hover\:bg-surface-700:where(.dark,.dark *):hover{background-color:var(--p-surface-700)}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-surface-700:where(.dark,.dark *):hover{background-color:color-mix(in srgb, var(--p-surface-700) calc(100% * 1), transparent)}}}}@keyframes enter{0%{opacity:var(--p-enter-opacity,1);transform:translate3d(var(--p-enter-translate-x,0), var(--p-enter-translate-y,0), 0) scale3d(var(--p-enter-scale,1), var(--p-enter-scale,1), var(--p-enter-scale,1)) rotate(var(--p-enter-rotate,0))}}@keyframes leave{to{opacity:var(--p-leave-opacity,1);transform:translate3d(var(--p-leave-translate-x,0), var(--p-leave-translate-y,0), 0) scale3d(var(--p-leave-scale,1), var(--p-leave-scale,1), var(--p-leave-scale,1)) rotate(var(--p-leave-rotate,0))}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}
|
|
@@ -70,6 +70,19 @@ class ClientInstancePreview {
|
|
|
70
70
|
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
71
71
|
response = signal(null, ...(ngDevMode ? [{ debugName: "response" }] : /* istanbul ignore next */ []));
|
|
72
72
|
entities = computed(() => mapPreviewToEntities(this.response(), this.config().displayAreas ?? ['card']), ...(ngDevMode ? [{ debugName: "entities" }] : /* istanbul ignore next */ []));
|
|
73
|
+
/**
|
|
74
|
+
* Name of the schema the loaded record belongs to — the level name for a
|
|
75
|
+
* `level:{id}` context, the module name for a `.../module:{id}` one. Hosts
|
|
76
|
+
* read it to title the preview (e.g. "{Level Name} Details"). Null until the
|
|
77
|
+
* fetch resolves.
|
|
78
|
+
*/
|
|
79
|
+
schemaName = computed(() => {
|
|
80
|
+
const response = this.response();
|
|
81
|
+
const schemas = response?.schemas ?? [];
|
|
82
|
+
const schemaId = response?.record?.schemaId;
|
|
83
|
+
const schema = schemas.find((candidate) => candidate.id === schemaId) ?? schemas[0];
|
|
84
|
+
return schema?.name || null;
|
|
85
|
+
}, ...(ngDevMode ? [{ debugName: "schemaName" }] : /* istanbul ignore next */ []));
|
|
73
86
|
constructor() {
|
|
74
87
|
effect(() => {
|
|
75
88
|
const config = this.config();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"masterteam-client-components-client-instance-preview.mjs","sources":["../../../../packages/masterteam/client-components/client-instance-preview/client-instance-preview-api.service.ts","../../../../packages/masterteam/client-components/client-instance-preview/client-instance-preview.ts","../../../../packages/masterteam/client-components/client-instance-preview/client-instance-preview.html","../../../../packages/masterteam/client-components/client-instance-preview/masterteam-client-components-client-instance-preview.ts"],"sourcesContent":["import { Injectable, inject } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { map, Observable } from 'rxjs';\r\nimport {\r\n ClientInstancePreviewConfig,\r\n PreviewFetchRecordResponse,\r\n PreviewResponse,\r\n Response,\r\n} from './client-instance-preview.model';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class ClientInstancePreviewApiService {\r\n private readonly http = inject(HttpClient);\r\n private readonly fetchBaseUrl = 'fetch';\r\n\r\n resolve(\r\n config: ClientInstancePreviewConfig,\r\n ): Observable<Response<PreviewResponse>> {\r\n const contextKey = config.contextKey;\r\n const areaKeys = config.displayAreas?.length\r\n ? config.displayAreas\r\n : ['card'];\r\n\r\n return this.http\r\n .get<Response<PreviewFetchRecordResponse>>(\r\n `${this.fetchBaseUrl}/records/${config.instanceId}`,\r\n {\r\n params: this.buildRecordPreviewParams(contextKey, areaKeys),\r\n },\r\n )\r\n .pipe(\r\n map((recordResponse) => ({\r\n endpoint: recordResponse.endpoint,\r\n status: recordResponse.status,\r\n code: recordResponse.code,\r\n locale: recordResponse.locale,\r\n message: recordResponse.message,\r\n errors: recordResponse.errors,\r\n cacheSession: recordResponse.cacheSession,\r\n data: {\r\n contextKey: recordResponse.data?.contextKey ?? contextKey,\r\n schemas: recordResponse.data?.schemas ?? [],\r\n catalog: recordResponse.data?.catalog ?? { properties: [] },\r\n record: recordResponse.data?.record ?? null,\r\n displayConfigurations:\r\n recordResponse.data?.projectionMeta?.displayOrder ?? [],\r\n },\r\n })),\r\n );\r\n }\r\n\r\n private buildRecordPreviewParams(\r\n contextKey: string,\r\n areaKeys: string[],\r\n ): Record<string, string> {\r\n const params: Record<string, string> = {\r\n contextKey,\r\n Projection: 'Card',\r\n };\r\n\r\n areaKeys.forEach((areaKey, index) => {\r\n params[`Display[areas][${index}]`] = areaKey;\r\n });\r\n\r\n return params;\r\n }\r\n}\r\n","import {\r\n Component,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n OnDestroy,\r\n signal,\r\n untracked,\r\n} from '@angular/core';\r\nimport { TranslocoPipe, TranslocoService } from '@jsverse/transloco';\r\nimport { Subscription } from 'rxjs';\r\n\r\nimport {\r\n EntitiesPreview,\r\n EntityData,\r\n EntityNestedPropertyMeta,\r\n EntitySectionLabel,\r\n isSectionKey,\r\n resolveLocalizedLabel,\r\n} from '@masterteam/components/entities';\r\n\r\nimport { ClientInstancePreviewApiService } from './client-instance-preview-api.service';\r\nimport {\r\n ClientInstancePreviewConfig,\r\n DisplayConfiguration,\r\n PreviewFetchPropertyMeta,\r\n PreviewFetchValueCell,\r\n PreviewResponse,\r\n} from './client-instance-preview.model';\r\n\r\n@Component({\r\n selector: 'mt-client-instance-preview',\r\n standalone: true,\r\n imports: [EntitiesPreview, TranslocoPipe],\r\n templateUrl: './client-instance-preview.html',\r\n})\r\nexport class ClientInstancePreview implements OnDestroy {\r\n private readonly clientInstancePreviewApiService = inject(\r\n ClientInstancePreviewApiService,\r\n );\r\n private readonly transloco = inject(TranslocoService);\r\n private loadSub?: Subscription;\r\n\r\n readonly config = input.required<ClientInstancePreviewConfig>();\r\n /** When true, suppresses the \"No preview data\" empty-state placeholder so the host can collapse. */\r\n readonly hideEmptyState = input<boolean>(false);\r\n /**\r\n * Forwarded to the inner `mt-entities-preview`. When `true` (default) every\r\n * field collapses to full width below a ~400px container width; pass `false`\r\n * from a host wide enough that each entity's `size` configuration should be\r\n * honored instead. The hard ≤280px overflow stack always applies regardless.\r\n */\r\n readonly stackOnNarrow = input<boolean>(true);\r\n readonly loading = signal(false);\r\n readonly error = signal<string | null>(null);\r\n readonly response = signal<PreviewResponse | null>(null);\r\n\r\n readonly entities = computed(() =>\r\n mapPreviewToEntities(\r\n this.response(),\r\n this.config().displayAreas ?? ['card'],\r\n ),\r\n );\r\n\r\n constructor() {\r\n effect(() => {\r\n const config = this.config();\r\n if (!config) {\r\n return;\r\n }\r\n\r\n untracked(() => this.load(config));\r\n });\r\n }\r\n\r\n load(config: ClientInstancePreviewConfig): void {\r\n this.loadSub?.unsubscribe();\r\n this.loading.set(true);\r\n this.error.set(null);\r\n\r\n this.loadSub = this.clientInstancePreviewApiService\r\n .resolve(config)\r\n .subscribe({\r\n next: (response) => {\r\n this.loading.set(false);\r\n this.response.set(response.data);\r\n },\r\n error: (error) => {\r\n this.loading.set(false);\r\n this.response.set(null);\r\n const message =\r\n error?.error?.message ??\r\n error?.message ??\r\n this.transloco.translate(\r\n 'components.clientComponents.instancePreview.loadFailed',\r\n );\r\n this.error.set(message);\r\n },\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.loadSub?.unsubscribe();\r\n }\r\n}\r\n\r\nfunction mapPreviewToEntities(\r\n response: PreviewResponse | null,\r\n areaKeys: string[],\r\n): EntityData[] {\r\n const record = response?.record;\r\n if (!record) {\r\n return [];\r\n }\r\n\r\n const properties = response?.catalog?.properties ?? [];\r\n const nestedProperties = response?.catalog?.nestedProperties ?? {};\r\n const propertyByKey = new Map(\r\n properties.map((property) => [property.key, property]),\r\n );\r\n const displayConfigurationsByPropertyKey =\r\n buildDisplayConfigurationsByPropertyKey(\r\n response?.displayConfigurations ?? [],\r\n areaKeys,\r\n );\r\n const lang = resolveActiveLang();\r\n\r\n // Iterate the display configs (not the catalog) so section markers — which\r\n // have no backing catalog property — are emitted too.\r\n const entities: EntityData[] = [];\r\n for (const [\r\n propertyKey,\r\n configuration,\r\n ] of displayConfigurationsByPropertyKey) {\r\n if (isSectionKey(propertyKey)) {\r\n entities.push(toSectionEntity(configuration, record.id, lang));\r\n continue;\r\n }\r\n const property = propertyByKey.get(propertyKey);\r\n if (!property) {\r\n continue;\r\n }\r\n entities.push(\r\n toEntityData(\r\n property,\r\n record.values?.[property.key],\r\n configuration,\r\n record.id,\r\n nestedProperties[property.key],\r\n lang,\r\n ),\r\n );\r\n }\r\n return entities;\r\n}\r\n\r\nfunction toSectionEntity(\r\n configuration: DisplayConfiguration,\r\n recordId: number,\r\n lang: string,\r\n): EntityData {\r\n const label = configuration.configuration?.['label'] as\r\n | EntitySectionLabel\r\n | undefined;\r\n return {\r\n id: recordId,\r\n key: configuration.propertyKey,\r\n normalizedKey: configuration.propertyKey,\r\n name: resolveLocalizedLabel(label, lang),\r\n value: '',\r\n viewType: 'Section',\r\n order: configuration.order,\r\n configuration: configuration.configuration as EntityData['configuration'],\r\n };\r\n}\r\n\r\nfunction resolveActiveLang(): string {\r\n if (typeof document === 'undefined') return 'en';\r\n return document.documentElement.lang || 'en';\r\n}\r\n\r\nfunction buildDisplayConfigurationsByPropertyKey(\r\n displayConfigurations: DisplayConfiguration[],\r\n areaKeys: string[],\r\n): Map<string, DisplayConfiguration> {\r\n const result = new Map<string, DisplayConfiguration>();\r\n const filteredConfigurations = displayConfigurations.filter((configuration) =>\r\n areaKeys.includes(configuration.areaKey),\r\n );\r\n const source =\r\n filteredConfigurations.length > 0\r\n ? filteredConfigurations\r\n : displayConfigurations;\r\n\r\n for (const configuration of source) {\r\n if (!configuration.propertyKey || result.has(configuration.propertyKey)) {\r\n continue;\r\n }\r\n\r\n result.set(configuration.propertyKey, configuration);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction toEntityData(\r\n meta: PreviewFetchPropertyMeta,\r\n cell: PreviewFetchValueCell | undefined,\r\n displayConfiguration: DisplayConfiguration | undefined,\r\n recordId: number,\r\n nestedProperties: PreviewFetchPropertyMeta[] | undefined,\r\n lang: string,\r\n): EntityData {\r\n const viewType = (meta?.viewType ?? 'Text') as EntityData['viewType'];\r\n // Custom label override saved on the display config wins over the catalog label.\r\n const customLabel = resolveLocalizedLabel(\r\n displayConfiguration?.configuration?.['label'] as\r\n | EntitySectionLabel\r\n | undefined,\r\n lang,\r\n );\r\n\r\n return {\r\n id: recordId,\r\n propertyId: meta?.id,\r\n key: meta.key,\r\n normalizedKey: meta.normalizedKey,\r\n name: customLabel || meta.label,\r\n rawValue:\r\n cell?.raw === null || cell?.raw === undefined\r\n ? undefined\r\n : String(cell.raw),\r\n value: toEntityValue(cell),\r\n viewType,\r\n type: meta?.source,\r\n order: displayConfiguration?.order ?? meta.order,\r\n configuration: displayConfiguration?.configuration ?? undefined,\r\n propertyConfiguration: meta.configuration ?? undefined,\r\n nestedProperties: nestedProperties?.map(toNestedPropertyMeta),\r\n comparison: cell?.comparison,\r\n };\r\n}\r\n\r\nfunction toNestedPropertyMeta(\r\n meta: PreviewFetchPropertyMeta,\r\n): EntityNestedPropertyMeta {\r\n return {\r\n id: meta.id,\r\n key: meta.key,\r\n normalizedKey: meta.normalizedKey,\r\n label: meta.label,\r\n viewType: (meta.viewType ?? 'Text') as EntityData['viewType'],\r\n configuration: meta.configuration ?? undefined,\r\n order: meta.order,\r\n };\r\n}\r\n\r\nfunction toEntityValue(\r\n cell: PreviewFetchValueCell | undefined,\r\n): EntityData['value'] {\r\n return (cell?.value ?? '') as EntityData['value'];\r\n}\r\n","@if (loading()) {\r\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\r\n @for (item of [1, 2, 3, 4]; track item) {\r\n <div class=\"rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"mb-3 h-4 w-28 animate-pulse rounded bg-surface-200\"></div>\r\n <div class=\"h-5 w-40 animate-pulse rounded bg-surface-200\"></div>\r\n </div>\r\n }\r\n </div>\r\n} @else if (error()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ error() }}\r\n </p>\r\n </div>\r\n} @else if (entities().length) {\r\n <mt-entities-preview\r\n [entities]=\"entities()\"\r\n [stackOnNarrow]=\"stackOnNarrow()\"\r\n />\r\n} @else if (!hideEmptyState()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{\r\n \"components.clientComponents.instancePreview.noPreviewData\" | transloco\r\n }}\r\n </p>\r\n </div>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"masterteam-client-components-client-instance-preview.mjs","sources":["../../../../packages/masterteam/client-components/client-instance-preview/client-instance-preview-api.service.ts","../../../../packages/masterteam/client-components/client-instance-preview/client-instance-preview.ts","../../../../packages/masterteam/client-components/client-instance-preview/client-instance-preview.html","../../../../packages/masterteam/client-components/client-instance-preview/masterteam-client-components-client-instance-preview.ts"],"sourcesContent":["import { Injectable, inject } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { map, Observable } from 'rxjs';\r\nimport {\r\n ClientInstancePreviewConfig,\r\n PreviewFetchRecordResponse,\r\n PreviewResponse,\r\n Response,\r\n} from './client-instance-preview.model';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class ClientInstancePreviewApiService {\r\n private readonly http = inject(HttpClient);\r\n private readonly fetchBaseUrl = 'fetch';\r\n\r\n resolve(\r\n config: ClientInstancePreviewConfig,\r\n ): Observable<Response<PreviewResponse>> {\r\n const contextKey = config.contextKey;\r\n const areaKeys = config.displayAreas?.length\r\n ? config.displayAreas\r\n : ['card'];\r\n\r\n return this.http\r\n .get<Response<PreviewFetchRecordResponse>>(\r\n `${this.fetchBaseUrl}/records/${config.instanceId}`,\r\n {\r\n params: this.buildRecordPreviewParams(contextKey, areaKeys),\r\n },\r\n )\r\n .pipe(\r\n map((recordResponse) => ({\r\n endpoint: recordResponse.endpoint,\r\n status: recordResponse.status,\r\n code: recordResponse.code,\r\n locale: recordResponse.locale,\r\n message: recordResponse.message,\r\n errors: recordResponse.errors,\r\n cacheSession: recordResponse.cacheSession,\r\n data: {\r\n contextKey: recordResponse.data?.contextKey ?? contextKey,\r\n schemas: recordResponse.data?.schemas ?? [],\r\n catalog: recordResponse.data?.catalog ?? { properties: [] },\r\n record: recordResponse.data?.record ?? null,\r\n displayConfigurations:\r\n recordResponse.data?.projectionMeta?.displayOrder ?? [],\r\n },\r\n })),\r\n );\r\n }\r\n\r\n private buildRecordPreviewParams(\r\n contextKey: string,\r\n areaKeys: string[],\r\n ): Record<string, string> {\r\n const params: Record<string, string> = {\r\n contextKey,\r\n Projection: 'Card',\r\n };\r\n\r\n areaKeys.forEach((areaKey, index) => {\r\n params[`Display[areas][${index}]`] = areaKey;\r\n });\r\n\r\n return params;\r\n }\r\n}\r\n","import {\r\n Component,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n OnDestroy,\r\n signal,\r\n untracked,\r\n} from '@angular/core';\r\nimport { TranslocoPipe, TranslocoService } from '@jsverse/transloco';\r\nimport { Subscription } from 'rxjs';\r\n\r\nimport {\r\n EntitiesPreview,\r\n EntityData,\r\n EntityNestedPropertyMeta,\r\n EntitySectionLabel,\r\n isSectionKey,\r\n resolveLocalizedLabel,\r\n} from '@masterteam/components/entities';\r\n\r\nimport { ClientInstancePreviewApiService } from './client-instance-preview-api.service';\r\nimport {\r\n ClientInstancePreviewConfig,\r\n DisplayConfiguration,\r\n PreviewFetchPropertyMeta,\r\n PreviewFetchValueCell,\r\n PreviewResponse,\r\n} from './client-instance-preview.model';\r\n\r\n@Component({\r\n selector: 'mt-client-instance-preview',\r\n standalone: true,\r\n imports: [EntitiesPreview, TranslocoPipe],\r\n templateUrl: './client-instance-preview.html',\r\n})\r\nexport class ClientInstancePreview implements OnDestroy {\r\n private readonly clientInstancePreviewApiService = inject(\r\n ClientInstancePreviewApiService,\r\n );\r\n private readonly transloco = inject(TranslocoService);\r\n private loadSub?: Subscription;\r\n\r\n readonly config = input.required<ClientInstancePreviewConfig>();\r\n /** When true, suppresses the \"No preview data\" empty-state placeholder so the host can collapse. */\r\n readonly hideEmptyState = input<boolean>(false);\r\n /**\r\n * Forwarded to the inner `mt-entities-preview`. When `true` (default) every\r\n * field collapses to full width below a ~400px container width; pass `false`\r\n * from a host wide enough that each entity's `size` configuration should be\r\n * honored instead. The hard ≤280px overflow stack always applies regardless.\r\n */\r\n readonly stackOnNarrow = input<boolean>(true);\r\n readonly loading = signal(false);\r\n readonly error = signal<string | null>(null);\r\n readonly response = signal<PreviewResponse | null>(null);\r\n\r\n readonly entities = computed(() =>\r\n mapPreviewToEntities(\r\n this.response(),\r\n this.config().displayAreas ?? ['card'],\r\n ),\r\n );\r\n /**\r\n * Name of the schema the loaded record belongs to — the level name for a\r\n * `level:{id}` context, the module name for a `.../module:{id}` one. Hosts\r\n * read it to title the preview (e.g. \"{Level Name} Details\"). Null until the\r\n * fetch resolves.\r\n */\r\n readonly schemaName = computed(() => {\r\n const response = this.response();\r\n const schemas = response?.schemas ?? [];\r\n const schemaId = response?.record?.schemaId;\r\n const schema =\r\n schemas.find((candidate) => candidate.id === schemaId) ?? schemas[0];\r\n\r\n return schema?.name || null;\r\n });\r\n\r\n constructor() {\r\n effect(() => {\r\n const config = this.config();\r\n if (!config) {\r\n return;\r\n }\r\n\r\n untracked(() => this.load(config));\r\n });\r\n }\r\n\r\n load(config: ClientInstancePreviewConfig): void {\r\n this.loadSub?.unsubscribe();\r\n this.loading.set(true);\r\n this.error.set(null);\r\n\r\n this.loadSub = this.clientInstancePreviewApiService\r\n .resolve(config)\r\n .subscribe({\r\n next: (response) => {\r\n this.loading.set(false);\r\n this.response.set(response.data);\r\n },\r\n error: (error) => {\r\n this.loading.set(false);\r\n this.response.set(null);\r\n const message =\r\n error?.error?.message ??\r\n error?.message ??\r\n this.transloco.translate(\r\n 'components.clientComponents.instancePreview.loadFailed',\r\n );\r\n this.error.set(message);\r\n },\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.loadSub?.unsubscribe();\r\n }\r\n}\r\n\r\nfunction mapPreviewToEntities(\r\n response: PreviewResponse | null,\r\n areaKeys: string[],\r\n): EntityData[] {\r\n const record = response?.record;\r\n if (!record) {\r\n return [];\r\n }\r\n\r\n const properties = response?.catalog?.properties ?? [];\r\n const nestedProperties = response?.catalog?.nestedProperties ?? {};\r\n const propertyByKey = new Map(\r\n properties.map((property) => [property.key, property]),\r\n );\r\n const displayConfigurationsByPropertyKey =\r\n buildDisplayConfigurationsByPropertyKey(\r\n response?.displayConfigurations ?? [],\r\n areaKeys,\r\n );\r\n const lang = resolveActiveLang();\r\n\r\n // Iterate the display configs (not the catalog) so section markers — which\r\n // have no backing catalog property — are emitted too.\r\n const entities: EntityData[] = [];\r\n for (const [\r\n propertyKey,\r\n configuration,\r\n ] of displayConfigurationsByPropertyKey) {\r\n if (isSectionKey(propertyKey)) {\r\n entities.push(toSectionEntity(configuration, record.id, lang));\r\n continue;\r\n }\r\n const property = propertyByKey.get(propertyKey);\r\n if (!property) {\r\n continue;\r\n }\r\n entities.push(\r\n toEntityData(\r\n property,\r\n record.values?.[property.key],\r\n configuration,\r\n record.id,\r\n nestedProperties[property.key],\r\n lang,\r\n ),\r\n );\r\n }\r\n return entities;\r\n}\r\n\r\nfunction toSectionEntity(\r\n configuration: DisplayConfiguration,\r\n recordId: number,\r\n lang: string,\r\n): EntityData {\r\n const label = configuration.configuration?.['label'] as\r\n | EntitySectionLabel\r\n | undefined;\r\n return {\r\n id: recordId,\r\n key: configuration.propertyKey,\r\n normalizedKey: configuration.propertyKey,\r\n name: resolveLocalizedLabel(label, lang),\r\n value: '',\r\n viewType: 'Section',\r\n order: configuration.order,\r\n configuration: configuration.configuration as EntityData['configuration'],\r\n };\r\n}\r\n\r\nfunction resolveActiveLang(): string {\r\n if (typeof document === 'undefined') return 'en';\r\n return document.documentElement.lang || 'en';\r\n}\r\n\r\nfunction buildDisplayConfigurationsByPropertyKey(\r\n displayConfigurations: DisplayConfiguration[],\r\n areaKeys: string[],\r\n): Map<string, DisplayConfiguration> {\r\n const result = new Map<string, DisplayConfiguration>();\r\n const filteredConfigurations = displayConfigurations.filter((configuration) =>\r\n areaKeys.includes(configuration.areaKey),\r\n );\r\n const source =\r\n filteredConfigurations.length > 0\r\n ? filteredConfigurations\r\n : displayConfigurations;\r\n\r\n for (const configuration of source) {\r\n if (!configuration.propertyKey || result.has(configuration.propertyKey)) {\r\n continue;\r\n }\r\n\r\n result.set(configuration.propertyKey, configuration);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction toEntityData(\r\n meta: PreviewFetchPropertyMeta,\r\n cell: PreviewFetchValueCell | undefined,\r\n displayConfiguration: DisplayConfiguration | undefined,\r\n recordId: number,\r\n nestedProperties: PreviewFetchPropertyMeta[] | undefined,\r\n lang: string,\r\n): EntityData {\r\n const viewType = (meta?.viewType ?? 'Text') as EntityData['viewType'];\r\n // Custom label override saved on the display config wins over the catalog label.\r\n const customLabel = resolveLocalizedLabel(\r\n displayConfiguration?.configuration?.['label'] as\r\n | EntitySectionLabel\r\n | undefined,\r\n lang,\r\n );\r\n\r\n return {\r\n id: recordId,\r\n propertyId: meta?.id,\r\n key: meta.key,\r\n normalizedKey: meta.normalizedKey,\r\n name: customLabel || meta.label,\r\n rawValue:\r\n cell?.raw === null || cell?.raw === undefined\r\n ? undefined\r\n : String(cell.raw),\r\n value: toEntityValue(cell),\r\n viewType,\r\n type: meta?.source,\r\n order: displayConfiguration?.order ?? meta.order,\r\n configuration: displayConfiguration?.configuration ?? undefined,\r\n propertyConfiguration: meta.configuration ?? undefined,\r\n nestedProperties: nestedProperties?.map(toNestedPropertyMeta),\r\n comparison: cell?.comparison,\r\n };\r\n}\r\n\r\nfunction toNestedPropertyMeta(\r\n meta: PreviewFetchPropertyMeta,\r\n): EntityNestedPropertyMeta {\r\n return {\r\n id: meta.id,\r\n key: meta.key,\r\n normalizedKey: meta.normalizedKey,\r\n label: meta.label,\r\n viewType: (meta.viewType ?? 'Text') as EntityData['viewType'],\r\n configuration: meta.configuration ?? undefined,\r\n order: meta.order,\r\n };\r\n}\r\n\r\nfunction toEntityValue(\r\n cell: PreviewFetchValueCell | undefined,\r\n): EntityData['value'] {\r\n return (cell?.value ?? '') as EntityData['value'];\r\n}\r\n","@if (loading()) {\r\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\r\n @for (item of [1, 2, 3, 4]; track item) {\r\n <div class=\"rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"mb-3 h-4 w-28 animate-pulse rounded bg-surface-200\"></div>\r\n <div class=\"h-5 w-40 animate-pulse rounded bg-surface-200\"></div>\r\n </div>\r\n }\r\n </div>\r\n} @else if (error()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ error() }}\r\n </p>\r\n </div>\r\n} @else if (entities().length) {\r\n <mt-entities-preview\r\n [entities]=\"entities()\"\r\n [stackOnNarrow]=\"stackOnNarrow()\"\r\n />\r\n} @else if (!hideEmptyState()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{\r\n \"components.clientComponents.instancePreview.noPreviewData\" | transloco\r\n }}\r\n </p>\r\n </div>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injectable, signal, computed, input, output, Component, effect, untracked } from '@angular/core';
|
|
2
|
+
import { inject, Injectable, signal, computed, input, output, Component, viewChild, effect, untracked } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
4
|
import { CommonModule } from '@angular/common';
|
|
5
5
|
import * as i4 from '@jsverse/transloco';
|
|
@@ -834,7 +834,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
834
834
|
args: [{ selector: 'mt-client-list-table-view', standalone: true, imports: [CommonModule, Table, SkeletonModule], template: "<div class=\"grid gap-4\" [style.gridTemplateColumns]=\"gridTemplateColumns\">\r\n @if (table().config.contentStart) {\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.startSpan)\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"table().config.contentStart\"\r\n [ngTemplateOutletContext]=\"templateContext(table())\"\r\n />\r\n </div>\r\n }\r\n\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.tableSpan)\">\r\n @if (table().loading && table().rows.length === 0) {\r\n <div class=\"flex flex-col gap-3 py-3\">\r\n <p-skeleton height=\"3rem\" />\r\n <p-skeleton height=\"3rem\" />\r\n <p-skeleton height=\"3rem\" />\r\n </div>\r\n } @else if (table().error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\"\r\n >\r\n {{ table().error }}\r\n </div>\r\n } @else {\r\n <mt-table\r\n [noCard]=\"true\"\r\n [data]=\"table().rows\"\r\n [columns]=\"table().columns\"\r\n dataKey=\"Id\"\r\n [storageKey]=\"tableStorageKey()\"\r\n [persistStateExclude]=\"table().config.table.persistStateExclude\"\r\n [rowActions]=\"rowActions()\"\r\n [actionShape]=\"actionShape()\"\r\n [rowActionsLoadingFn]=\"rowActionsLoadingFn()\"\r\n (rowActionsRequested)=\"rowActionsRequested.emit($event)\"\r\n [generalSearch]=\"table().config.table.searchable\"\r\n [showFilters]=\"true\"\r\n filterMode=\"column\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [cellClickFilter]=\"true\"\r\n [freezeActions]=\"true\"\r\n [exportable]=\"table().config.table.exportable\"\r\n [loading]=\"table().loading\"\r\n [clickableRows]=\"true\"\r\n [lazy]=\"table().config.isPaginated\"\r\n [lazyTotalRecords]=\"table().totalCount\"\r\n [virtualScroll]=\"!table().config.isPaginated\"\r\n [virtualScrollItemSize]=\"56\"\r\n scrollHeight=\"520px\"\r\n [pageSize]=\"pageSize()\"\r\n [filters]=\"bucket().filters()\"\r\n (filtersChange)=\"bucket().filters.set($event)\"\r\n [filterTerm]=\"bucket().filterTerm()\"\r\n (filterTermChange)=\"bucket().filterTerm.set($event)\"\r\n [groupBy]=\"bucket().groupBy()\"\r\n (groupByChange)=\"bucket().groupBy.set($event)\"\r\n [activeTab]=\"bucket().activeTab()\"\r\n (activeTabChange)=\"bucket().activeTab.set($event)\"\r\n (lazyLoad)=\"lazyLoad.emit($event)\"\r\n (rowClick)=\"rowClick.emit($event)\"\r\n />\r\n }\r\n </div>\r\n\r\n @if (table().config.contentEnd) {\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.endSpan)\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"table().config.contentEnd\"\r\n [ngTemplateOutletContext]=\"templateContext(table())\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n" }]
|
|
835
835
|
}], propDecorators: { state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: true }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], actionShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionShape", required: false }] }], rowActionsLoadingFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActionsLoadingFn", required: false }] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowActionsRequested: [{ type: i0.Output, args: ["rowActionsRequested"] }] } });
|
|
836
836
|
|
|
837
|
+
/**
|
|
838
|
+
* Render-window helpers for the cards view.
|
|
839
|
+
*
|
|
840
|
+
* The cards grid keeps a bounded number of cards in the DOM and grows that
|
|
841
|
+
* window as the user scrolls. Search, filtering, grouping, counts, and export
|
|
842
|
+
* all keep operating on the full result set — only rendering is windowed.
|
|
843
|
+
*/
|
|
844
|
+
/**
|
|
845
|
+
* Fill groups in order until the render budget runs out.
|
|
846
|
+
*
|
|
847
|
+
* A group that fits entirely is passed through untouched (same object identity,
|
|
848
|
+
* so `track` keys stay stable); a group that straddles the budget is copied
|
|
849
|
+
* with a truncated `cards` array. `count` is never rewritten — the header badge
|
|
850
|
+
* must keep reporting the group's true size, not how much of it is rendered.
|
|
851
|
+
*/
|
|
852
|
+
function windowCardGroups(groups, limit) {
|
|
853
|
+
let remaining = limit;
|
|
854
|
+
const windowed = [];
|
|
855
|
+
for (const group of groups) {
|
|
856
|
+
if (remaining <= 0)
|
|
857
|
+
break;
|
|
858
|
+
windowed.push(remaining >= group.cards.length
|
|
859
|
+
? group
|
|
860
|
+
: { ...group, cards: group.cards.slice(0, remaining) });
|
|
861
|
+
remaining -= group.cards.length;
|
|
862
|
+
}
|
|
863
|
+
return windowed;
|
|
864
|
+
}
|
|
865
|
+
|
|
837
866
|
const EMPTY_KEY_SET = new Set();
|
|
867
|
+
/**
|
|
868
|
+
* How many cards the grid puts in the DOM at once. The window grows by another
|
|
869
|
+
* chunk each time the sentinel below the grid nears the viewport, so a level
|
|
870
|
+
* holding 350 records starts as 60 grid children instead of 350 and stays
|
|
871
|
+
* responsive as the workspace grows.
|
|
872
|
+
*
|
|
873
|
+
* This is deliberately *not* a fixed-height virtual viewport: an earlier
|
|
874
|
+
* attempt wrapped every card in a fixed `h-80` row so a scroller could compute
|
|
875
|
+
* item offsets, which clipped taller cards and had to be reverted. Windowing
|
|
876
|
+
* the same `@for` leaves the existing grid, card markup, and natural card
|
|
877
|
+
* heights completely untouched.
|
|
878
|
+
*/
|
|
879
|
+
const CARD_RENDER_CHUNK = 60;
|
|
880
|
+
/** Grow the window before the sentinel is actually on screen. */
|
|
881
|
+
const CARD_RENDER_ROOT_MARGIN = '600px';
|
|
838
882
|
class ClientListCardsView {
|
|
839
883
|
toolbar = inject(ClientListToolbarService);
|
|
840
884
|
exportService = inject(TableExportService);
|
|
@@ -1067,7 +1111,7 @@ class ClientListCardsView {
|
|
|
1067
1111
|
* Grouped cards. Reuses TableGroupingController helpers so the accent color,
|
|
1068
1112
|
* label, and count rendering match the table's subheader exactly.
|
|
1069
1113
|
*/
|
|
1070
|
-
|
|
1114
|
+
allGroupedCards = computed(() => {
|
|
1071
1115
|
const column = this.grouping.activeGroupColumn();
|
|
1072
1116
|
if (!column)
|
|
1073
1117
|
return [];
|
|
@@ -1094,7 +1138,46 @@ class ClientListCardsView {
|
|
|
1094
1138
|
}
|
|
1095
1139
|
});
|
|
1096
1140
|
return Array.from(groups.values());
|
|
1097
|
-
}, ...(ngDevMode ? [{ debugName: "
|
|
1141
|
+
}, ...(ngDevMode ? [{ debugName: "allGroupedCards" }] : /* istanbul ignore next */ []));
|
|
1142
|
+
// ==========================================================================
|
|
1143
|
+
// Render window
|
|
1144
|
+
//
|
|
1145
|
+
// Search, filters, grouping, counts, and export all keep operating on the
|
|
1146
|
+
// full `visibleCards()` set — only what reaches the DOM is windowed.
|
|
1147
|
+
// ==========================================================================
|
|
1148
|
+
/** Windowing needs the sentinel to observe; without it, render everything. */
|
|
1149
|
+
supportsIntersectionObserver = typeof IntersectionObserver !== 'undefined';
|
|
1150
|
+
renderLimit = signal(this.initialRenderLimit(), ...(ngDevMode ? [{ debugName: "renderLimit" }] : /* istanbul ignore next */ []));
|
|
1151
|
+
loadMoreSentinel = viewChild('loadMoreSentinel', ...(ngDevMode ? [{ debugName: "loadMoreSentinel" }] : /* istanbul ignore next */ []));
|
|
1152
|
+
initialRenderLimit() {
|
|
1153
|
+
return this.supportsIntersectionObserver
|
|
1154
|
+
? CARD_RENDER_CHUNK
|
|
1155
|
+
: Number.POSITIVE_INFINITY;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Identity of the current result set. Any change — list swap, search, filter,
|
|
1159
|
+
* group toggle — restarts the window at the first chunk, so a freshly
|
|
1160
|
+
* filtered set never opens scrolled into the middle of the previous one.
|
|
1161
|
+
*/
|
|
1162
|
+
renderWindowKey = computed(() => {
|
|
1163
|
+
const bucket = this.bucket();
|
|
1164
|
+
return JSON.stringify([
|
|
1165
|
+
this.cardsState().key,
|
|
1166
|
+
bucket.filterTerm(),
|
|
1167
|
+
bucket.filters(),
|
|
1168
|
+
this.grouping.activeGroupColumn()?.key ?? null,
|
|
1169
|
+
]);
|
|
1170
|
+
}, ...(ngDevMode ? [{ debugName: "renderWindowKey" }] : /* istanbul ignore next */ []));
|
|
1171
|
+
/** Cards put in the DOM by the ungrouped grid. */
|
|
1172
|
+
renderedCards = computed(() => this.visibleCards().slice(0, this.renderLimit()), ...(ngDevMode ? [{ debugName: "renderedCards" }] : /* istanbul ignore next */ []));
|
|
1173
|
+
/**
|
|
1174
|
+
* Grouped view of the window. Groups are filled in order until the budget
|
|
1175
|
+
* runs out; `count` stays the group's true size so the header badge keeps
|
|
1176
|
+
* reporting the full number rather than what happens to be rendered.
|
|
1177
|
+
*/
|
|
1178
|
+
groupedCards = computed(() => windowCardGroups(this.allGroupedCards(), this.renderLimit()), ...(ngDevMode ? [{ debugName: "groupedCards" }] : /* istanbul ignore next */ []));
|
|
1179
|
+
/** True while cards are still being held back from the DOM. */
|
|
1180
|
+
hasMoreCards = computed(() => this.visibleCards().length > this.renderLimit(), ...(ngDevMode ? [{ debugName: "hasMoreCards" }] : /* istanbul ignore next */ []));
|
|
1098
1181
|
/**
|
|
1099
1182
|
* Export the visible (after search + filter) cards as XLSX. Uses the cards'
|
|
1100
1183
|
* derived row shape + the state's columns, so the file mirrors what the
|
|
@@ -1248,6 +1331,30 @@ class ClientListCardsView {
|
|
|
1248
1331
|
return null;
|
|
1249
1332
|
}
|
|
1250
1333
|
constructor() {
|
|
1334
|
+
// Restart the render window whenever the underlying result set changes.
|
|
1335
|
+
effect(() => {
|
|
1336
|
+
this.renderWindowKey();
|
|
1337
|
+
untracked(() => this.renderLimit.set(this.initialRenderLimit()));
|
|
1338
|
+
});
|
|
1339
|
+
// Grow the window as the sentinel below the grid approaches the viewport.
|
|
1340
|
+
// `root: null` measures against the viewport with ancestor clipping applied,
|
|
1341
|
+
// so this works whether the page scrolls or an inner container does.
|
|
1342
|
+
effect((onCleanup) => {
|
|
1343
|
+
const sentinel = this.loadMoreSentinel()?.nativeElement;
|
|
1344
|
+
if (!sentinel)
|
|
1345
|
+
return;
|
|
1346
|
+
const observer = new IntersectionObserver((entries) => {
|
|
1347
|
+
if (!entries.some((entry) => entry.isIntersecting))
|
|
1348
|
+
return;
|
|
1349
|
+
untracked(() => {
|
|
1350
|
+
if (this.visibleCards().length <= this.renderLimit())
|
|
1351
|
+
return;
|
|
1352
|
+
this.renderLimit.update((limit) => limit + CARD_RENDER_CHUNK);
|
|
1353
|
+
});
|
|
1354
|
+
}, { rootMargin: CARD_RENDER_ROOT_MARGIN });
|
|
1355
|
+
observer.observe(sentinel);
|
|
1356
|
+
onCleanup(() => observer.disconnect());
|
|
1357
|
+
});
|
|
1251
1358
|
// Emit lazyLoad only on filter / search changes for paginated lists,
|
|
1252
1359
|
// matching mt-table's behaviour (group-by is a pure FE concern, not a
|
|
1253
1360
|
// re-fetch trigger). Skip the initial firing while the bucket is still at
|
|
@@ -1276,7 +1383,7 @@ class ClientListCardsView {
|
|
|
1276
1383
|
});
|
|
1277
1384
|
}
|
|
1278
1385
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ClientListCardsView, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1279
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ClientListCardsView, isStandalone: true, selector: "mt-client-list-cards-view", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: true, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, rowActionsLoadingFn: { classPropertyName: "rowActionsLoadingFn", publicName: "rowActionsLoadingFn", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { lazyLoad: "lazyLoad", cardClick: "cardClick", rowActionsRequested: "rowActionsRequested" }, providers: [MTDateFormatPipe], ngImport: i0, template: "<mt-table-caption\r\n [generalSearch]=\"true\"\r\n [showFilters]=\"true\"\r\n filterMode=\"popover\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [exportable]=\"true\"\r\n [columns]=\"columns()\"\r\n [data]=\"rowRepresentations()\"\r\n [groupColumns]=\"grouping.groupableColumns()\"\r\n [filters]=\"bucket().filters()\"\r\n (filtersChange)=\"bucket().filters.set($event)\"\r\n [filterTerm]=\"bucket().filterTerm()\"\r\n (filterTermChange)=\"bucket().filterTerm.set($event)\"\r\n [groupBy]=\"bucket().groupBy()\"\r\n (groupByChange)=\"bucket().groupBy.set($event)\"\r\n [activeTab]=\"bucket().activeTab()\"\r\n (activeTabChange)=\"bucket().activeTab.set($event)\"\r\n (exportRequested)=\"exportExcel()\"\r\n (printRequested)=\"printPdf()\"\r\n/>\r\n\r\n@if (cardsState().loading && cardsState().cards.length === 0) {\r\n <div class=\"grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"20rem\" class=\"rounded-lg\" />\r\n }\r\n </div>\r\n} @else if (cardsState().error) {\r\n <div class=\"rounded-lg border border-red-200 bg-red-50 p-6 text-red-600\">\r\n {{ cardsState().error }}\r\n </div>\r\n} @else if (visibleCards().length === 0) {\r\n <div class=\"p-6 text-center text-gray-400\">\r\n {{ \"components.clientComponents.list.noCardsFound\" | transloco }}\r\n </div>\r\n} @else if (grouping.groupingActive()) {\r\n <div class=\"flex flex-col gap-6\">\r\n @for (group of groupedCards(); track group.key) {\r\n <section class=\"flex flex-col gap-3\">\r\n <header\r\n class=\"flex items-center gap-3 px-2 py-2 bg-surface-50 dark:bg-surface-900 border-y border-surface-200 dark:border-surface-700 rounded\"\r\n [style.--mt-group-accent]=\"group.accent ?? 'var(--p-primary-color)'\"\r\n >\r\n <span\r\n class=\"inline-block w-1 h-5 rounded-full\"\r\n [style.background]=\"'var(--mt-group-accent)'\"\r\n ></span>\r\n <span\r\n class=\"text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400\"\r\n >\r\n {{ group.columnLabel }}\r\n </span>\r\n <span class=\"text-sm font-semibold text-gray-900 dark:text-gray-100\">\r\n {{ group.label }}\r\n </span>\r\n <span\r\n class=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full bg-primary-50 text-primary-700 dark:bg-primary-950 dark:text-primary-300\"\r\n >\r\n {{ group.count }}\r\n </span>\r\n </header>\r\n <div class=\"grid grid-cols-1 gap-5 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (card of group.cards; track card.id) {\r\n <mt-card\r\n class=\"relative cursor-pointer p-5 shadow-sm transition-shadow hover:shadow-md\"\r\n (click)=\"cardClick.emit(card)\"\r\n >\r\n <ng-template #headless>\r\n <ng-container\r\n [ngTemplateOutlet]=\"cardActionsMenu\"\r\n [ngTemplateOutletContext]=\"{ $implicit: card }\"\r\n />\r\n <mt-entities-preview\r\n [entities]=\"card.entities\"\r\n attachmentShape=\"compact\"\r\n [stackOnNarrow]=\"false\"\r\n [clickableKeys]=\"clickableEntityKeys()\"\r\n [activeKeys]=\"activeKeysForCard(card)\"\r\n [clickableTooltip]=\"\r\n 'components.table.filterByThis' | transloco\r\n \"\r\n [activeTooltip]=\"'components.table.clearFilter' | transloco\"\r\n (entityClick)=\"onEntityFilterClick(card, $event)\"\r\n />\r\n </ng-template>\r\n </mt-card>\r\n }\r\n </div>\r\n </section>\r\n }\r\n </div>\r\n} @else {\r\n <div class=\"grid grid-cols-1 gap-5 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (card of visibleCards(); track card.id) {\r\n @defer (on viewport) {\r\n <mt-card\r\n class=\"relative cursor-pointer p-5 shadow-sm transition-shadow hover:shadow-md\"\r\n (click)=\"cardClick.emit(card)\"\r\n >\r\n <ng-template #headless>\r\n <ng-container\r\n [ngTemplateOutlet]=\"cardActionsMenu\"\r\n [ngTemplateOutletContext]=\"{ $implicit: card }\"\r\n />\r\n <mt-entities-preview\r\n [entities]=\"card.entities\"\r\n attachmentShape=\"compact\"\r\n [stackOnNarrow]=\"false\"\r\n [clickableKeys]=\"clickableEntityKeys()\"\r\n [activeKeys]=\"activeKeysForCard(card)\"\r\n [clickableTooltip]=\"'components.table.filterByThis' | transloco\"\r\n [activeTooltip]=\"'components.table.clearFilter' | transloco\"\r\n (entityClick)=\"onEntityFilterClick(card, $event)\"\r\n />\r\n </ng-template>\r\n </mt-card>\r\n } @placeholder {\r\n <div class=\"min-h-[20rem]\">\r\n <p-skeleton height=\"20rem\" class=\"rounded-lg\" />\r\n </div>\r\n }\r\n }\r\n </div>\r\n}\r\n\r\n<!--\r\n Per-card 3-dots actions menu \u2014 same contract as the table view's popover\r\n row-actions. Rendered into each card's top-end corner; clicks stop at the\r\n wrapper so the card's own click (cardClick) doesn't fire.\r\n-->\r\n<ng-template #cardActionsMenu let-card>\r\n @if (rowActions().length > 0) {\r\n <div\r\n class=\"absolute end-2 top-2 z-10 flex items-center gap-1\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n @for (action of inlineActionsForCard(card); track $index) {\r\n <mt-button\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.color\"\r\n [variant]=\"action.variant\"\r\n [size]=\"actionSize(action) || 'small'\"\r\n [tooltip]=\"action.tooltip\"\r\n [label]=\"action.label\"\r\n [loading]=\"resolveActionLoading(action, card)\"\r\n (onClick)=\"runCardAction($event, action, card)\"\r\n />\r\n }\r\n @if (showCardActionsMenu(card)) {\r\n <mt-button\r\n icon=\"general.dots-vertical\"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n [tooltip]=\"'components.table.actions' | transloco\"\r\n (onClick)=\"onCardActionsToggle($event, cardPopover, card)\"\r\n />\r\n <p-popover #cardPopover appendTo=\"body\">\r\n <div class=\"flex min-w-44 flex-col gap-1 p-1\">\r\n @if (isCardActionsLoading(card)) {\r\n <div class=\"flex flex-col gap-2 p-1\">\r\n <p-skeleton height=\"1.75rem\" />\r\n <p-skeleton height=\"1.75rem\" />\r\n <p-skeleton height=\"1.75rem\" />\r\n </div>\r\n } @else {\r\n @for (action of menuActionsForCard(card); track $index) {\r\n <button\r\n type=\"button\"\r\n class=\"flex cursor-pointer items-center gap-2 rounded px-2 py-2 text-start text-sm transition-colors\"\r\n [class]=\"\r\n action.color === 'danger'\r\n ? 'text-red-600 hover:bg-red-50 dark:hover:bg-red-950'\r\n : 'text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-surface-700'\r\n \"\r\n (click)=\"\r\n runCardAction($event, action, card); cardPopover.hide()\r\n \"\r\n >\r\n @if (action.icon) {\r\n <mt-icon [icon]=\"action.icon\" class=\"text-base\" />\r\n }\r\n <span>{{ action.label || action.tooltip }}</span>\r\n </button>\r\n }\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities", "attachmentShape", "stackOnNarrow", "clickableKeys", "activeKeys", "clickableTooltip", "activeTooltip"], outputs: ["entityClick"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i3.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: TableCaption, selector: "mt-table-caption", inputs: ["generalSearch", "showFilters", "filterMode", "exportable", "printable", "groupable", "columns", "data", "groupColumns", "tabs", "tabsOptionLabel", "tabsOptionValue", "actions", "captionStart", "captionEnd", "activeTab", "filters", "filterTerm", "groupBy"], outputs: ["activeTabChange", "filtersChange", "filterTermChange", "groupByChange", "exportRequested", "printRequested", "onTabChange", "searchChange", "filterApplied", "filterReset"] }, { kind: "pipe", type: i4.TranslocoPipe, name: "transloco" }], deferBlockDependencies: [() => [i1.NgTemplateOutlet, Card,
|
|
1386
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: ClientListCardsView, isStandalone: true, selector: "mt-client-list-cards-view", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: true, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, rowActionsLoadingFn: { classPropertyName: "rowActionsLoadingFn", publicName: "rowActionsLoadingFn", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { lazyLoad: "lazyLoad", cardClick: "cardClick", rowActionsRequested: "rowActionsRequested" }, providers: [MTDateFormatPipe], viewQueries: [{ propertyName: "loadMoreSentinel", first: true, predicate: ["loadMoreSentinel"], descendants: true, isSignal: true }], ngImport: i0, template: "<mt-table-caption\r\n [generalSearch]=\"true\"\r\n [showFilters]=\"true\"\r\n filterMode=\"popover\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [exportable]=\"true\"\r\n [columns]=\"columns()\"\r\n [data]=\"rowRepresentations()\"\r\n [groupColumns]=\"grouping.groupableColumns()\"\r\n [filters]=\"bucket().filters()\"\r\n (filtersChange)=\"bucket().filters.set($event)\"\r\n [filterTerm]=\"bucket().filterTerm()\"\r\n (filterTermChange)=\"bucket().filterTerm.set($event)\"\r\n [groupBy]=\"bucket().groupBy()\"\r\n (groupByChange)=\"bucket().groupBy.set($event)\"\r\n [activeTab]=\"bucket().activeTab()\"\r\n (activeTabChange)=\"bucket().activeTab.set($event)\"\r\n (exportRequested)=\"exportExcel()\"\r\n (printRequested)=\"printPdf()\"\r\n/>\r\n\r\n@if (cardsState().loading && cardsState().cards.length === 0) {\r\n <div class=\"grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"20rem\" class=\"rounded-lg\" />\r\n }\r\n </div>\r\n} @else if (cardsState().error) {\r\n <div class=\"rounded-lg border border-red-200 bg-red-50 p-6 text-red-600\">\r\n {{ cardsState().error }}\r\n </div>\r\n} @else if (visibleCards().length === 0) {\r\n <div class=\"p-6 text-center text-gray-400\">\r\n {{ \"components.clientComponents.list.noCardsFound\" | transloco }}\r\n </div>\r\n} @else if (grouping.groupingActive()) {\r\n <div class=\"flex flex-col gap-6\">\r\n @for (group of groupedCards(); track group.key) {\r\n <section class=\"flex flex-col gap-3\">\r\n <header\r\n class=\"flex items-center gap-3 px-2 py-2 bg-surface-50 dark:bg-surface-900 border-y border-surface-200 dark:border-surface-700 rounded\"\r\n [style.--mt-group-accent]=\"group.accent ?? 'var(--p-primary-color)'\"\r\n >\r\n <span\r\n class=\"inline-block w-1 h-5 rounded-full\"\r\n [style.background]=\"'var(--mt-group-accent)'\"\r\n ></span>\r\n <span\r\n class=\"text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400\"\r\n >\r\n {{ group.columnLabel }}\r\n </span>\r\n <span class=\"text-sm font-semibold text-gray-900 dark:text-gray-100\">\r\n {{ group.label }}\r\n </span>\r\n <span\r\n class=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full bg-primary-50 text-primary-700 dark:bg-primary-950 dark:text-primary-300\"\r\n >\r\n {{ group.count }}\r\n </span>\r\n </header>\r\n <div class=\"grid grid-cols-1 gap-5 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (card of group.cards; track card.id) {\r\n <mt-card\r\n class=\"relative cursor-pointer p-5 shadow-sm transition-shadow hover:shadow-md\"\r\n (click)=\"cardClick.emit(card)\"\r\n >\r\n <ng-template #headless>\r\n <ng-container\r\n [ngTemplateOutlet]=\"cardActionsMenu\"\r\n [ngTemplateOutletContext]=\"{ $implicit: card }\"\r\n />\r\n <mt-entities-preview\r\n [entities]=\"card.entities\"\r\n attachmentShape=\"compact\"\r\n [stackOnNarrow]=\"false\"\r\n [clickableKeys]=\"clickableEntityKeys()\"\r\n [activeKeys]=\"activeKeysForCard(card)\"\r\n [clickableTooltip]=\"\r\n 'components.table.filterByThis' | transloco\r\n \"\r\n [activeTooltip]=\"'components.table.clearFilter' | transloco\"\r\n (entityClick)=\"onEntityFilterClick(card, $event)\"\r\n />\r\n </ng-template>\r\n </mt-card>\r\n }\r\n </div>\r\n </section>\r\n }\r\n </div>\r\n} @else {\r\n <div class=\"grid grid-cols-1 gap-5 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (card of renderedCards(); track card.id) {\r\n @defer (on viewport) {\r\n <mt-card\r\n class=\"relative cursor-pointer p-5 shadow-sm transition-shadow hover:shadow-md\"\r\n (click)=\"cardClick.emit(card)\"\r\n >\r\n <ng-template #headless>\r\n <ng-container\r\n [ngTemplateOutlet]=\"cardActionsMenu\"\r\n [ngTemplateOutletContext]=\"{ $implicit: card }\"\r\n />\r\n <mt-entities-preview\r\n [entities]=\"card.entities\"\r\n attachmentShape=\"compact\"\r\n [stackOnNarrow]=\"false\"\r\n [clickableKeys]=\"clickableEntityKeys()\"\r\n [activeKeys]=\"activeKeysForCard(card)\"\r\n [clickableTooltip]=\"'components.table.filterByThis' | transloco\"\r\n [activeTooltip]=\"'components.table.clearFilter' | transloco\"\r\n (entityClick)=\"onEntityFilterClick(card, $event)\"\r\n />\r\n </ng-template>\r\n </mt-card>\r\n } @placeholder {\r\n <div class=\"min-h-[20rem]\">\r\n <p-skeleton height=\"20rem\" class=\"rounded-lg\" />\r\n </div>\r\n }\r\n }\r\n </div>\r\n}\r\n\r\n<!--\r\n Render-window sentinel. Sits after the grid (never inside it, so it is not a\r\n grid child) and grows the window as it approaches the viewport. Removed from\r\n the DOM once every card is rendered.\r\n-->\r\n@if (hasMoreCards()) {\r\n <div #loadMoreSentinel class=\"h-px w-full\" aria-hidden=\"true\"></div>\r\n}\r\n\r\n<!--\r\n Per-card 3-dots actions menu \u2014 same contract as the table view's popover\r\n row-actions. Rendered into each card's top-end corner; clicks stop at the\r\n wrapper so the card's own click (cardClick) doesn't fire.\r\n-->\r\n<ng-template #cardActionsMenu let-card>\r\n @if (rowActions().length > 0) {\r\n <div\r\n class=\"absolute end-2 top-2 z-10 flex items-center gap-1\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n @for (action of inlineActionsForCard(card); track $index) {\r\n <mt-button\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.color\"\r\n [variant]=\"action.variant\"\r\n [size]=\"actionSize(action) || 'small'\"\r\n [tooltip]=\"action.tooltip\"\r\n [label]=\"action.label\"\r\n [loading]=\"resolveActionLoading(action, card)\"\r\n (onClick)=\"runCardAction($event, action, card)\"\r\n />\r\n }\r\n @if (showCardActionsMenu(card)) {\r\n <mt-button\r\n icon=\"general.dots-vertical\"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n [tooltip]=\"'components.table.actions' | transloco\"\r\n (onClick)=\"onCardActionsToggle($event, cardPopover, card)\"\r\n />\r\n <p-popover #cardPopover appendTo=\"body\">\r\n <div class=\"flex min-w-44 flex-col gap-1 p-1\">\r\n @if (isCardActionsLoading(card)) {\r\n <div class=\"flex flex-col gap-2 p-1\">\r\n <p-skeleton height=\"1.75rem\" />\r\n <p-skeleton height=\"1.75rem\" />\r\n <p-skeleton height=\"1.75rem\" />\r\n </div>\r\n } @else {\r\n @for (action of menuActionsForCard(card); track $index) {\r\n <button\r\n type=\"button\"\r\n class=\"flex cursor-pointer items-center gap-2 rounded px-2 py-2 text-start text-sm transition-colors\"\r\n [class]=\"\r\n action.color === 'danger'\r\n ? 'text-red-600 hover:bg-red-50 dark:hover:bg-red-950'\r\n : 'text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-surface-700'\r\n \"\r\n (click)=\"\r\n runCardAction($event, action, card); cardPopover.hide()\r\n \"\r\n >\r\n @if (action.icon) {\r\n <mt-icon [icon]=\"action.icon\" class=\"text-base\" />\r\n }\r\n <span>{{ action.label || action.tooltip }}</span>\r\n </button>\r\n }\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities", "attachmentShape", "stackOnNarrow", "clickableKeys", "activeKeys", "clickableTooltip", "activeTooltip"], outputs: ["entityClick"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i3.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: TableCaption, selector: "mt-table-caption", inputs: ["generalSearch", "showFilters", "filterMode", "exportable", "printable", "groupable", "columns", "data", "groupColumns", "tabs", "tabsOptionLabel", "tabsOptionValue", "actions", "captionStart", "captionEnd", "activeTab", "filters", "filterTerm", "groupBy"], outputs: ["activeTabChange", "filtersChange", "filterTermChange", "groupByChange", "exportRequested", "printRequested", "onTabChange", "searchChange", "filterApplied", "filterReset"] }, { kind: "pipe", type: i4.TranslocoPipe, name: "transloco" }], deferBlockDependencies: [() => [i1.NgTemplateOutlet, Card,
|
|
1280
1387
|
EntitiesPreview, i4.TranslocoPipe]] });
|
|
1281
1388
|
}
|
|
1282
1389
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: ClientListCardsView, decorators: [{
|
|
@@ -1291,8 +1398,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1291
1398
|
SkeletonModule,
|
|
1292
1399
|
PopoverModule,
|
|
1293
1400
|
TableCaption,
|
|
1294
|
-
], providers: [MTDateFormatPipe], template: "<mt-table-caption\r\n [generalSearch]=\"true\"\r\n [showFilters]=\"true\"\r\n filterMode=\"popover\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [exportable]=\"true\"\r\n [columns]=\"columns()\"\r\n [data]=\"rowRepresentations()\"\r\n [groupColumns]=\"grouping.groupableColumns()\"\r\n [filters]=\"bucket().filters()\"\r\n (filtersChange)=\"bucket().filters.set($event)\"\r\n [filterTerm]=\"bucket().filterTerm()\"\r\n (filterTermChange)=\"bucket().filterTerm.set($event)\"\r\n [groupBy]=\"bucket().groupBy()\"\r\n (groupByChange)=\"bucket().groupBy.set($event)\"\r\n [activeTab]=\"bucket().activeTab()\"\r\n (activeTabChange)=\"bucket().activeTab.set($event)\"\r\n (exportRequested)=\"exportExcel()\"\r\n (printRequested)=\"printPdf()\"\r\n/>\r\n\r\n@if (cardsState().loading && cardsState().cards.length === 0) {\r\n <div class=\"grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"20rem\" class=\"rounded-lg\" />\r\n }\r\n </div>\r\n} @else if (cardsState().error) {\r\n <div class=\"rounded-lg border border-red-200 bg-red-50 p-6 text-red-600\">\r\n {{ cardsState().error }}\r\n </div>\r\n} @else if (visibleCards().length === 0) {\r\n <div class=\"p-6 text-center text-gray-400\">\r\n {{ \"components.clientComponents.list.noCardsFound\" | transloco }}\r\n </div>\r\n} @else if (grouping.groupingActive()) {\r\n <div class=\"flex flex-col gap-6\">\r\n @for (group of groupedCards(); track group.key) {\r\n <section class=\"flex flex-col gap-3\">\r\n <header\r\n class=\"flex items-center gap-3 px-2 py-2 bg-surface-50 dark:bg-surface-900 border-y border-surface-200 dark:border-surface-700 rounded\"\r\n [style.--mt-group-accent]=\"group.accent ?? 'var(--p-primary-color)'\"\r\n >\r\n <span\r\n class=\"inline-block w-1 h-5 rounded-full\"\r\n [style.background]=\"'var(--mt-group-accent)'\"\r\n ></span>\r\n <span\r\n class=\"text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400\"\r\n >\r\n {{ group.columnLabel }}\r\n </span>\r\n <span class=\"text-sm font-semibold text-gray-900 dark:text-gray-100\">\r\n {{ group.label }}\r\n </span>\r\n <span\r\n class=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full bg-primary-50 text-primary-700 dark:bg-primary-950 dark:text-primary-300\"\r\n >\r\n {{ group.count }}\r\n </span>\r\n </header>\r\n <div class=\"grid grid-cols-1 gap-5 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (card of group.cards; track card.id) {\r\n <mt-card\r\n class=\"relative cursor-pointer p-5 shadow-sm transition-shadow hover:shadow-md\"\r\n (click)=\"cardClick.emit(card)\"\r\n >\r\n <ng-template #headless>\r\n <ng-container\r\n [ngTemplateOutlet]=\"cardActionsMenu\"\r\n [ngTemplateOutletContext]=\"{ $implicit: card }\"\r\n />\r\n <mt-entities-preview\r\n [entities]=\"card.entities\"\r\n attachmentShape=\"compact\"\r\n [stackOnNarrow]=\"false\"\r\n [clickableKeys]=\"clickableEntityKeys()\"\r\n [activeKeys]=\"activeKeysForCard(card)\"\r\n [clickableTooltip]=\"\r\n 'components.table.filterByThis' | transloco\r\n \"\r\n [activeTooltip]=\"'components.table.clearFilter' | transloco\"\r\n (entityClick)=\"onEntityFilterClick(card, $event)\"\r\n />\r\n </ng-template>\r\n </mt-card>\r\n }\r\n </div>\r\n </section>\r\n }\r\n </div>\r\n} @else {\r\n <div class=\"grid grid-cols-1 gap-5 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (card of
|
|
1295
|
-
}], ctorParameters: () => [], propDecorators: { state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: true }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], rowActionsLoadingFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActionsLoadingFn", required: false }] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], cardClick: [{ type: i0.Output, args: ["cardClick"] }], rowActionsRequested: [{ type: i0.Output, args: ["rowActionsRequested"] }] } });
|
|
1401
|
+
], providers: [MTDateFormatPipe], template: "<mt-table-caption\r\n [generalSearch]=\"true\"\r\n [showFilters]=\"true\"\r\n filterMode=\"popover\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [exportable]=\"true\"\r\n [columns]=\"columns()\"\r\n [data]=\"rowRepresentations()\"\r\n [groupColumns]=\"grouping.groupableColumns()\"\r\n [filters]=\"bucket().filters()\"\r\n (filtersChange)=\"bucket().filters.set($event)\"\r\n [filterTerm]=\"bucket().filterTerm()\"\r\n (filterTermChange)=\"bucket().filterTerm.set($event)\"\r\n [groupBy]=\"bucket().groupBy()\"\r\n (groupByChange)=\"bucket().groupBy.set($event)\"\r\n [activeTab]=\"bucket().activeTab()\"\r\n (activeTabChange)=\"bucket().activeTab.set($event)\"\r\n (exportRequested)=\"exportExcel()\"\r\n (printRequested)=\"printPdf()\"\r\n/>\r\n\r\n@if (cardsState().loading && cardsState().cards.length === 0) {\r\n <div class=\"grid grid-cols-1 gap-6 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (i of [1, 2, 3, 4, 5, 6]; track i) {\r\n <p-skeleton height=\"20rem\" class=\"rounded-lg\" />\r\n }\r\n </div>\r\n} @else if (cardsState().error) {\r\n <div class=\"rounded-lg border border-red-200 bg-red-50 p-6 text-red-600\">\r\n {{ cardsState().error }}\r\n </div>\r\n} @else if (visibleCards().length === 0) {\r\n <div class=\"p-6 text-center text-gray-400\">\r\n {{ \"components.clientComponents.list.noCardsFound\" | transloco }}\r\n </div>\r\n} @else if (grouping.groupingActive()) {\r\n <div class=\"flex flex-col gap-6\">\r\n @for (group of groupedCards(); track group.key) {\r\n <section class=\"flex flex-col gap-3\">\r\n <header\r\n class=\"flex items-center gap-3 px-2 py-2 bg-surface-50 dark:bg-surface-900 border-y border-surface-200 dark:border-surface-700 rounded\"\r\n [style.--mt-group-accent]=\"group.accent ?? 'var(--p-primary-color)'\"\r\n >\r\n <span\r\n class=\"inline-block w-1 h-5 rounded-full\"\r\n [style.background]=\"'var(--mt-group-accent)'\"\r\n ></span>\r\n <span\r\n class=\"text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400\"\r\n >\r\n {{ group.columnLabel }}\r\n </span>\r\n <span class=\"text-sm font-semibold text-gray-900 dark:text-gray-100\">\r\n {{ group.label }}\r\n </span>\r\n <span\r\n class=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full bg-primary-50 text-primary-700 dark:bg-primary-950 dark:text-primary-300\"\r\n >\r\n {{ group.count }}\r\n </span>\r\n </header>\r\n <div class=\"grid grid-cols-1 gap-5 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (card of group.cards; track card.id) {\r\n <mt-card\r\n class=\"relative cursor-pointer p-5 shadow-sm transition-shadow hover:shadow-md\"\r\n (click)=\"cardClick.emit(card)\"\r\n >\r\n <ng-template #headless>\r\n <ng-container\r\n [ngTemplateOutlet]=\"cardActionsMenu\"\r\n [ngTemplateOutletContext]=\"{ $implicit: card }\"\r\n />\r\n <mt-entities-preview\r\n [entities]=\"card.entities\"\r\n attachmentShape=\"compact\"\r\n [stackOnNarrow]=\"false\"\r\n [clickableKeys]=\"clickableEntityKeys()\"\r\n [activeKeys]=\"activeKeysForCard(card)\"\r\n [clickableTooltip]=\"\r\n 'components.table.filterByThis' | transloco\r\n \"\r\n [activeTooltip]=\"'components.table.clearFilter' | transloco\"\r\n (entityClick)=\"onEntityFilterClick(card, $event)\"\r\n />\r\n </ng-template>\r\n </mt-card>\r\n }\r\n </div>\r\n </section>\r\n }\r\n </div>\r\n} @else {\r\n <div class=\"grid grid-cols-1 gap-5 md:grid-cols-2 xl:grid-cols-3\">\r\n @for (card of renderedCards(); track card.id) {\r\n @defer (on viewport) {\r\n <mt-card\r\n class=\"relative cursor-pointer p-5 shadow-sm transition-shadow hover:shadow-md\"\r\n (click)=\"cardClick.emit(card)\"\r\n >\r\n <ng-template #headless>\r\n <ng-container\r\n [ngTemplateOutlet]=\"cardActionsMenu\"\r\n [ngTemplateOutletContext]=\"{ $implicit: card }\"\r\n />\r\n <mt-entities-preview\r\n [entities]=\"card.entities\"\r\n attachmentShape=\"compact\"\r\n [stackOnNarrow]=\"false\"\r\n [clickableKeys]=\"clickableEntityKeys()\"\r\n [activeKeys]=\"activeKeysForCard(card)\"\r\n [clickableTooltip]=\"'components.table.filterByThis' | transloco\"\r\n [activeTooltip]=\"'components.table.clearFilter' | transloco\"\r\n (entityClick)=\"onEntityFilterClick(card, $event)\"\r\n />\r\n </ng-template>\r\n </mt-card>\r\n } @placeholder {\r\n <div class=\"min-h-[20rem]\">\r\n <p-skeleton height=\"20rem\" class=\"rounded-lg\" />\r\n </div>\r\n }\r\n }\r\n </div>\r\n}\r\n\r\n<!--\r\n Render-window sentinel. Sits after the grid (never inside it, so it is not a\r\n grid child) and grows the window as it approaches the viewport. Removed from\r\n the DOM once every card is rendered.\r\n-->\r\n@if (hasMoreCards()) {\r\n <div #loadMoreSentinel class=\"h-px w-full\" aria-hidden=\"true\"></div>\r\n}\r\n\r\n<!--\r\n Per-card 3-dots actions menu \u2014 same contract as the table view's popover\r\n row-actions. Rendered into each card's top-end corner; clicks stop at the\r\n wrapper so the card's own click (cardClick) doesn't fire.\r\n-->\r\n<ng-template #cardActionsMenu let-card>\r\n @if (rowActions().length > 0) {\r\n <div\r\n class=\"absolute end-2 top-2 z-10 flex items-center gap-1\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n @for (action of inlineActionsForCard(card); track $index) {\r\n <mt-button\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.color\"\r\n [variant]=\"action.variant\"\r\n [size]=\"actionSize(action) || 'small'\"\r\n [tooltip]=\"action.tooltip\"\r\n [label]=\"action.label\"\r\n [loading]=\"resolveActionLoading(action, card)\"\r\n (onClick)=\"runCardAction($event, action, card)\"\r\n />\r\n }\r\n @if (showCardActionsMenu(card)) {\r\n <mt-button\r\n icon=\"general.dots-vertical\"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n [tooltip]=\"'components.table.actions' | transloco\"\r\n (onClick)=\"onCardActionsToggle($event, cardPopover, card)\"\r\n />\r\n <p-popover #cardPopover appendTo=\"body\">\r\n <div class=\"flex min-w-44 flex-col gap-1 p-1\">\r\n @if (isCardActionsLoading(card)) {\r\n <div class=\"flex flex-col gap-2 p-1\">\r\n <p-skeleton height=\"1.75rem\" />\r\n <p-skeleton height=\"1.75rem\" />\r\n <p-skeleton height=\"1.75rem\" />\r\n </div>\r\n } @else {\r\n @for (action of menuActionsForCard(card); track $index) {\r\n <button\r\n type=\"button\"\r\n class=\"flex cursor-pointer items-center gap-2 rounded px-2 py-2 text-start text-sm transition-colors\"\r\n [class]=\"\r\n action.color === 'danger'\r\n ? 'text-red-600 hover:bg-red-50 dark:hover:bg-red-950'\r\n : 'text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-surface-700'\r\n \"\r\n (click)=\"\r\n runCardAction($event, action, card); cardPopover.hide()\r\n \"\r\n >\r\n @if (action.icon) {\r\n <mt-icon [icon]=\"action.icon\" class=\"text-base\" />\r\n }\r\n <span>{{ action.label || action.tooltip }}</span>\r\n </button>\r\n }\r\n }\r\n </div>\r\n </p-popover>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n" }]
|
|
1402
|
+
}], ctorParameters: () => [], propDecorators: { state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: true }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], rowActionsLoadingFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActionsLoadingFn", required: false }] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], cardClick: [{ type: i0.Output, args: ["cardClick"] }], rowActionsRequested: [{ type: i0.Output, args: ["rowActionsRequested"] }], loadMoreSentinel: [{ type: i0.ViewChild, args: ['loadMoreSentinel', { isSignal: true }] }] } });
|
|
1296
1403
|
|
|
1297
1404
|
function toDashboardExtraFilters(filters = []) {
|
|
1298
1405
|
const extraFilters = {};
|