@vendure/admin-ui 2.0.0-next.3 → 2.0.0-next.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/catalog/catalog.module.d.ts +10 -11
  2. package/catalog/components/collection-contents/collection-contents.component.d.ts +3 -1
  3. package/catalog/components/collection-detail/collection-detail.component.d.ts +2 -0
  4. package/catalog/public_api.d.ts +0 -1
  5. package/core/common/generated-types.d.ts +5 -0
  6. package/core/common/utilities/selection-manager.d.ts +23 -0
  7. package/core/common/version.d.ts +1 -1
  8. package/core/components/app-shell/app-shell.component.d.ts +1 -0
  9. package/core/public_api.d.ts +5 -0
  10. package/core/shared/components/asset-gallery/asset-gallery.component.d.ts +27 -3
  11. package/core/shared/components/configurable-input/configurable-input.component.d.ts +8 -3
  12. package/core/shared/components/product-multi-selector-dialog/product-multi-selector-dialog.component.d.ts +38 -0
  13. package/{catalog → core/shared}/components/product-search-input/product-search-input.component.d.ts +1 -1
  14. package/core/shared/components/select-toggle/select-toggle.component.d.ts +2 -1
  15. package/core/shared/dynamic-form-inputs/combination-mode-form-input/combination-mode-form-input.component.d.ts +28 -0
  16. package/core/shared/dynamic-form-inputs/product-multi-selector-form-input/product-multi-selector-form-input.component.d.ts +23 -0
  17. package/core/shared/dynamic-form-inputs/register-dynamic-input-components.d.ts +3 -1
  18. package/core/shared/dynamic-form-inputs/relation-form-input/asset/relation-asset-input.component.d.ts +6 -3
  19. package/core/shared/shared.module.d.ts +32 -28
  20. package/esm2020/catalog/catalog.module.mjs +1 -5
  21. package/esm2020/catalog/components/assets/assets.component.mjs +2 -2
  22. package/esm2020/catalog/components/collection-contents/collection-contents.component.mjs +12 -4
  23. package/esm2020/catalog/components/collection-detail/collection-detail.component.mjs +21 -6
  24. package/esm2020/catalog/components/collection-list/collection-list.component.mjs +1 -1
  25. package/esm2020/catalog/components/product-detail/product-detail.component.mjs +2 -2
  26. package/esm2020/catalog/components/product-list/product-list.component.mjs +7 -8
  27. package/esm2020/catalog/components/product-variants-list/product-variants-list.component.mjs +2 -2
  28. package/esm2020/catalog/public_api.mjs +1 -2
  29. package/esm2020/core/common/generated-types.mjs +1 -1
  30. package/esm2020/core/common/utilities/configurable-operation-utils.mjs +2 -2
  31. package/esm2020/core/common/utilities/selection-manager.mjs +64 -0
  32. package/esm2020/core/common/version.mjs +2 -2
  33. package/esm2020/core/components/app-shell/app-shell.component.mjs +6 -5
  34. package/esm2020/core/data/definitions/order-definitions.mjs +431 -430
  35. package/esm2020/core/public_api.mjs +6 -1
  36. package/esm2020/core/shared/components/asset-gallery/asset-gallery.component.mjs +33 -50
  37. package/esm2020/core/shared/components/configurable-input/configurable-input.component.mjs +15 -4
  38. package/esm2020/core/shared/components/product-multi-selector-dialog/product-multi-selector-dialog.component.mjs +135 -0
  39. package/esm2020/core/shared/components/product-search-input/product-search-input.component.mjs +108 -0
  40. package/esm2020/core/shared/components/rich-text-editor/rich-text-editor.component.mjs +2 -2
  41. package/esm2020/core/shared/components/select-toggle/select-toggle.component.mjs +6 -3
  42. package/esm2020/core/shared/dynamic-form-inputs/combination-mode-form-input/combination-mode-form-input.component.mjs +45 -0
  43. package/esm2020/core/shared/dynamic-form-inputs/product-multi-selector-form-input/product-multi-selector-form-input.component.mjs +48 -0
  44. package/esm2020/core/shared/dynamic-form-inputs/register-dynamic-input-components.mjs +5 -1
  45. package/esm2020/core/shared/dynamic-form-inputs/relation-form-input/asset/relation-asset-input.component.mjs +11 -9
  46. package/esm2020/core/shared/shared.module.mjs +21 -5
  47. package/esm2020/dashboard/components/dashboard/dashboard.component.mjs +2 -2
  48. package/esm2020/dashboard/components/dashboard-widget/dashboard-widget.component.mjs +2 -2
  49. package/esm2020/dashboard/widgets/order-summary-widget/order-summary-widget.component.mjs +2 -2
  50. package/esm2020/login/components/login/login.component.mjs +3 -3
  51. package/esm2020/marketing/components/promotion-detail/promotion-detail.component.mjs +3 -3
  52. package/esm2020/order/components/fulfill-order-dialog/fulfill-order-dialog.component.mjs +1 -1
  53. package/esm2020/order/components/order-list/order-list.component.mjs +3 -3
  54. package/esm2020/settings/components/payment-method-detail/payment-method-detail.component.mjs +1 -1
  55. package/esm2020/settings/components/permission-grid/permission-grid.component.mjs +1 -1
  56. package/esm2020/settings/components/shipping-method-detail/shipping-method-detail.component.mjs +1 -1
  57. package/fesm2015/vendure-admin-ui-catalog.mjs +41 -121
  58. package/fesm2015/vendure-admin-ui-catalog.mjs.map +1 -1
  59. package/fesm2015/vendure-admin-ui-core.mjs +1931 -1556
  60. package/fesm2015/vendure-admin-ui-core.mjs.map +1 -1
  61. package/fesm2015/vendure-admin-ui-dashboard.mjs +5 -5
  62. package/fesm2015/vendure-admin-ui-dashboard.mjs.map +1 -1
  63. package/fesm2015/vendure-admin-ui-login.mjs +2 -2
  64. package/fesm2015/vendure-admin-ui-login.mjs.map +1 -1
  65. package/fesm2015/vendure-admin-ui-marketing.mjs +2 -2
  66. package/fesm2015/vendure-admin-ui-marketing.mjs.map +1 -1
  67. package/fesm2015/vendure-admin-ui-order.mjs +3 -3
  68. package/fesm2015/vendure-admin-ui-order.mjs.map +1 -1
  69. package/fesm2015/vendure-admin-ui-settings.mjs +3 -3
  70. package/fesm2020/vendure-admin-ui-catalog.mjs +41 -121
  71. package/fesm2020/vendure-admin-ui-catalog.mjs.map +1 -1
  72. package/fesm2020/vendure-admin-ui-core.mjs +1928 -1556
  73. package/fesm2020/vendure-admin-ui-core.mjs.map +1 -1
  74. package/fesm2020/vendure-admin-ui-dashboard.mjs +5 -5
  75. package/fesm2020/vendure-admin-ui-dashboard.mjs.map +1 -1
  76. package/fesm2020/vendure-admin-ui-login.mjs +2 -2
  77. package/fesm2020/vendure-admin-ui-login.mjs.map +1 -1
  78. package/fesm2020/vendure-admin-ui-marketing.mjs +2 -2
  79. package/fesm2020/vendure-admin-ui-marketing.mjs.map +1 -1
  80. package/fesm2020/vendure-admin-ui-order.mjs +3 -3
  81. package/fesm2020/vendure-admin-ui-order.mjs.map +1 -1
  82. package/fesm2020/vendure-admin-ui-settings.mjs +3 -3
  83. package/package.json +2 -2
  84. package/static/i18n-messages/cs.json +10 -1
  85. package/static/i18n-messages/de.json +12 -1
  86. package/static/i18n-messages/en.json +10 -1
  87. package/static/i18n-messages/es.json +10 -1
  88. package/static/i18n-messages/fr.json +10 -1
  89. package/static/i18n-messages/it.json +10 -1
  90. package/static/i18n-messages/pl.json +10 -1
  91. package/static/i18n-messages/pt_BR.json +10 -1
  92. package/static/i18n-messages/pt_PT.json +10 -1
  93. package/static/i18n-messages/ru.json +10 -1
  94. package/static/i18n-messages/uk.json +10 -1
  95. package/static/i18n-messages/zh_Hans.json +10 -1
  96. package/static/i18n-messages/zh_Hant.json +10 -1
  97. package/static/styles/global/_forms.scss +1 -1
  98. package/static/styles/global/_overrides.scss +5 -1
  99. package/static/styles/theme/default.scss +13 -1
  100. package/static/theme.min.css +1 -1
  101. package/esm2020/catalog/components/product-search-input/product-search-input.component.mjs +0 -107
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Component, isDevMode, Inject, HostListener, ChangeDetectionStrategy, Input, EventEmitter, Output, Directive, Optional, Pipe, ViewChild, APP_INITIALIZER, Injector, NgModule, HostBinding, ContentChild, ChangeDetectorRef, ViewContainerRef, ViewChildren, TemplateRef, SkipSelf, forwardRef, ContentChildren, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
2
+ import { Injectable, Component, isDevMode, Inject, HostListener, ChangeDetectionStrategy, Input, EventEmitter, Output, Directive, Optional, Pipe, ViewChild, APP_INITIALIZER, Injector, NgModule, ChangeDetectorRef, ViewContainerRef, ViewChildren, forwardRef, HostBinding, ContentChild, TemplateRef, SkipSelf, ContentChildren, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
3
3
  import * as i3 from '@angular/common';
4
4
  import { DOCUMENT, CommonModule, PlatformLocation } from '@angular/common';
5
5
  import { concatMap, bufferCount, map, filter, distinctUntilChanged, skip, takeUntil, tap, take, finalize, switchMap, mergeMap, mapTo, catchError, startWith, shareReplay, throttleTime, scan, debounceTime, delay } from 'rxjs/operators';
@@ -24,7 +24,7 @@ import { TranslateMessageFormatCompiler, MESSAGE_FORMAT_CONFIG } from 'ngx-trans
24
24
  import * as i1$3 from '@clr/angular';
25
25
  import { ClarityModule } from '@clr/angular';
26
26
  import * as i2 from '@angular/forms';
27
- import { FormControl, NG_VALUE_ACCESSOR, FormArray, FormGroup, Validators, NG_VALIDATORS, FormsModule, ReactiveFormsModule } from '@angular/forms';
27
+ import { FormControl, FormArray, NG_VALUE_ACCESSOR, FormGroup, Validators, NG_VALIDATORS, FormsModule, ReactiveFormsModule } from '@angular/forms';
28
28
  import { DEFAULT_CHANNEL_CODE, DEFAULT_AUTH_TOKEN_HEADER_KEY } from '@vendure/common/lib/shared-constants';
29
29
  import { TemplatePortal } from '@angular/cdk/portal';
30
30
  import * as i1$4 from '@angular/cdk/overlay';
@@ -37,12 +37,12 @@ import { createUploadLink } from 'apollo-upload-client';
37
37
  import { omit } from '@vendure/common/lib/omit';
38
38
  import { __awaiter } from 'tslib';
39
39
  import { CodeJar } from 'codejar';
40
+ import * as i3$1 from '@angular/cdk/drag-drop';
41
+ import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
40
42
  import * as i2$1 from '@ng-select/ng-select';
41
43
  import { NgSelectComponent, SELECTION_MODEL_FACTORY, NgSelectModule } from '@ng-select/ng-select';
42
44
  import dayjs from 'dayjs';
43
45
  import * as i9 from '@angular/cdk/bidi';
44
- import * as i3$1 from '@angular/cdk/drag-drop';
45
- import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
46
46
  import * as i1$5 from 'ngx-pagination';
47
47
  import { PaginationService, NgxPaginationModule } from 'ngx-pagination';
48
48
  import { joinUp, joinDown, lift, selectParentNode, toggleMark, wrapIn, chainCommands, exitCode, setBlockType, baseKeymap } from 'prosemirror-commands';
@@ -2055,459 +2055,460 @@ class FacetDataService {
2055
2055
  }
2056
2056
  }
2057
2057
 
2058
- const DISCOUNT_FRAGMENT = gql `
2059
- fragment Discount on Discount {
2060
- adjustmentSource
2061
- amount
2062
- amountWithTax
2063
- description
2064
- type
2065
- }
2058
+ const DISCOUNT_FRAGMENT = gql `
2059
+ fragment Discount on Discount {
2060
+ adjustmentSource
2061
+ amount
2062
+ amountWithTax
2063
+ description
2064
+ type
2065
+ }
2066
2066
  `;
2067
- const REFUND_FRAGMENT = gql `
2068
- fragment Refund on Refund {
2069
- id
2070
- state
2071
- items
2072
- shipping
2073
- adjustment
2074
- transactionId
2075
- paymentId
2076
- }
2067
+ const REFUND_FRAGMENT = gql `
2068
+ fragment Refund on Refund {
2069
+ id
2070
+ state
2071
+ items
2072
+ shipping
2073
+ adjustment
2074
+ transactionId
2075
+ paymentId
2076
+ }
2077
2077
  `;
2078
- const ORDER_ADDRESS_FRAGMENT = gql `
2079
- fragment OrderAddress on OrderAddress {
2080
- fullName
2081
- company
2082
- streetLine1
2083
- streetLine2
2084
- city
2085
- province
2086
- postalCode
2087
- country
2088
- countryCode
2089
- phoneNumber
2090
- }
2078
+ const ORDER_ADDRESS_FRAGMENT = gql `
2079
+ fragment OrderAddress on OrderAddress {
2080
+ fullName
2081
+ company
2082
+ streetLine1
2083
+ streetLine2
2084
+ city
2085
+ province
2086
+ postalCode
2087
+ country
2088
+ countryCode
2089
+ phoneNumber
2090
+ }
2091
2091
  `;
2092
- const ORDER_FRAGMENT = gql `
2093
- fragment Order on Order {
2094
- id
2095
- createdAt
2096
- updatedAt
2097
- orderPlacedAt
2098
- code
2099
- state
2100
- nextStates
2101
- total
2102
- currencyCode
2103
- customer {
2104
- id
2105
- firstName
2106
- lastName
2107
- }
2108
- shippingLines {
2109
- shippingMethod {
2110
- name
2111
- }
2112
- }
2113
- }
2092
+ const ORDER_FRAGMENT = gql `
2093
+ fragment Order on Order {
2094
+ id
2095
+ createdAt
2096
+ updatedAt
2097
+ orderPlacedAt
2098
+ code
2099
+ state
2100
+ nextStates
2101
+ total
2102
+ totalWithTax
2103
+ currencyCode
2104
+ customer {
2105
+ id
2106
+ firstName
2107
+ lastName
2108
+ }
2109
+ shippingLines {
2110
+ shippingMethod {
2111
+ name
2112
+ }
2113
+ }
2114
+ }
2114
2115
  `;
2115
- const FULFILLMENT_FRAGMENT = gql `
2116
- fragment Fulfillment on Fulfillment {
2117
- id
2118
- state
2119
- nextStates
2120
- createdAt
2121
- updatedAt
2122
- method
2123
- orderItems {
2124
- id
2125
- }
2126
- trackingCode
2127
- }
2116
+ const FULFILLMENT_FRAGMENT = gql `
2117
+ fragment Fulfillment on Fulfillment {
2118
+ id
2119
+ state
2120
+ nextStates
2121
+ createdAt
2122
+ updatedAt
2123
+ method
2124
+ orderItems {
2125
+ id
2126
+ }
2127
+ trackingCode
2128
+ }
2128
2129
  `;
2129
- const ORDER_LINE_FRAGMENT = gql `
2130
- fragment OrderLine on OrderLine {
2131
- id
2132
- featuredAsset {
2133
- preview
2134
- }
2135
- productVariant {
2136
- id
2137
- name
2138
- sku
2139
- trackInventory
2140
- stockOnHand
2141
- }
2142
- discounts {
2143
- ...Discount
2144
- }
2145
- unitPrice
2146
- unitPriceWithTax
2147
- proratedUnitPrice
2148
- proratedUnitPriceWithTax
2149
- quantity
2150
- items {
2151
- id
2152
- unitPrice
2153
- unitPriceWithTax
2154
- taxRate
2155
- refundId
2156
- cancelled
2157
- fulfillment {
2158
- ...Fulfillment
2159
- }
2160
- }
2161
- linePrice
2162
- lineTax
2163
- linePriceWithTax
2164
- discountedLinePrice
2165
- discountedLinePriceWithTax
2166
- }
2130
+ const ORDER_LINE_FRAGMENT = gql `
2131
+ fragment OrderLine on OrderLine {
2132
+ id
2133
+ featuredAsset {
2134
+ preview
2135
+ }
2136
+ productVariant {
2137
+ id
2138
+ name
2139
+ sku
2140
+ trackInventory
2141
+ stockOnHand
2142
+ }
2143
+ discounts {
2144
+ ...Discount
2145
+ }
2146
+ unitPrice
2147
+ unitPriceWithTax
2148
+ proratedUnitPrice
2149
+ proratedUnitPriceWithTax
2150
+ quantity
2151
+ items {
2152
+ id
2153
+ unitPrice
2154
+ unitPriceWithTax
2155
+ taxRate
2156
+ refundId
2157
+ cancelled
2158
+ fulfillment {
2159
+ ...Fulfillment
2160
+ }
2161
+ }
2162
+ linePrice
2163
+ lineTax
2164
+ linePriceWithTax
2165
+ discountedLinePrice
2166
+ discountedLinePriceWithTax
2167
+ }
2167
2168
  `;
2168
- const ORDER_DETAIL_FRAGMENT = gql `
2169
- fragment OrderDetail on Order {
2170
- id
2171
- createdAt
2172
- updatedAt
2173
- code
2174
- state
2175
- nextStates
2176
- active
2177
- couponCodes
2178
- customer {
2179
- id
2180
- firstName
2181
- lastName
2182
- }
2183
- lines {
2184
- ...OrderLine
2185
- }
2186
- surcharges {
2187
- id
2188
- sku
2189
- description
2190
- price
2191
- priceWithTax
2192
- taxRate
2193
- }
2194
- discounts {
2195
- ...Discount
2196
- }
2197
- promotions {
2198
- id
2199
- couponCode
2200
- }
2201
- subTotal
2202
- subTotalWithTax
2203
- total
2204
- totalWithTax
2205
- currencyCode
2206
- shipping
2207
- shippingWithTax
2208
- shippingLines {
2209
- shippingMethod {
2210
- id
2211
- code
2212
- name
2213
- fulfillmentHandlerCode
2214
- description
2215
- }
2216
- }
2217
- taxSummary {
2218
- description
2219
- taxBase
2220
- taxRate
2221
- taxTotal
2222
- }
2223
- shippingAddress {
2224
- ...OrderAddress
2225
- }
2226
- billingAddress {
2227
- ...OrderAddress
2228
- }
2229
- payments {
2230
- id
2231
- createdAt
2232
- transactionId
2233
- amount
2234
- method
2235
- state
2236
- nextStates
2237
- errorMessage
2238
- metadata
2239
- refunds {
2240
- id
2241
- createdAt
2242
- state
2243
- items
2244
- adjustment
2245
- total
2246
- paymentId
2247
- reason
2248
- transactionId
2249
- method
2250
- metadata
2251
- orderItems {
2252
- id
2253
- }
2254
- }
2255
- }
2256
- fulfillments {
2257
- ...Fulfillment
2258
- }
2259
- modifications {
2260
- id
2261
- createdAt
2262
- isSettled
2263
- priceChange
2264
- note
2265
- payment {
2266
- id
2267
- amount
2268
- }
2269
- orderItems {
2270
- id
2271
- }
2272
- refund {
2273
- id
2274
- paymentId
2275
- total
2276
- }
2277
- surcharges {
2278
- id
2279
- }
2280
- }
2281
- }
2282
- ${DISCOUNT_FRAGMENT}
2283
- ${ORDER_ADDRESS_FRAGMENT}
2284
- ${FULFILLMENT_FRAGMENT}
2285
- ${ORDER_LINE_FRAGMENT}
2169
+ const ORDER_DETAIL_FRAGMENT = gql `
2170
+ fragment OrderDetail on Order {
2171
+ id
2172
+ createdAt
2173
+ updatedAt
2174
+ code
2175
+ state
2176
+ nextStates
2177
+ active
2178
+ couponCodes
2179
+ customer {
2180
+ id
2181
+ firstName
2182
+ lastName
2183
+ }
2184
+ lines {
2185
+ ...OrderLine
2186
+ }
2187
+ surcharges {
2188
+ id
2189
+ sku
2190
+ description
2191
+ price
2192
+ priceWithTax
2193
+ taxRate
2194
+ }
2195
+ discounts {
2196
+ ...Discount
2197
+ }
2198
+ promotions {
2199
+ id
2200
+ couponCode
2201
+ }
2202
+ subTotal
2203
+ subTotalWithTax
2204
+ total
2205
+ totalWithTax
2206
+ currencyCode
2207
+ shipping
2208
+ shippingWithTax
2209
+ shippingLines {
2210
+ shippingMethod {
2211
+ id
2212
+ code
2213
+ name
2214
+ fulfillmentHandlerCode
2215
+ description
2216
+ }
2217
+ }
2218
+ taxSummary {
2219
+ description
2220
+ taxBase
2221
+ taxRate
2222
+ taxTotal
2223
+ }
2224
+ shippingAddress {
2225
+ ...OrderAddress
2226
+ }
2227
+ billingAddress {
2228
+ ...OrderAddress
2229
+ }
2230
+ payments {
2231
+ id
2232
+ createdAt
2233
+ transactionId
2234
+ amount
2235
+ method
2236
+ state
2237
+ nextStates
2238
+ errorMessage
2239
+ metadata
2240
+ refunds {
2241
+ id
2242
+ createdAt
2243
+ state
2244
+ items
2245
+ adjustment
2246
+ total
2247
+ paymentId
2248
+ reason
2249
+ transactionId
2250
+ method
2251
+ metadata
2252
+ orderItems {
2253
+ id
2254
+ }
2255
+ }
2256
+ }
2257
+ fulfillments {
2258
+ ...Fulfillment
2259
+ }
2260
+ modifications {
2261
+ id
2262
+ createdAt
2263
+ isSettled
2264
+ priceChange
2265
+ note
2266
+ payment {
2267
+ id
2268
+ amount
2269
+ }
2270
+ orderItems {
2271
+ id
2272
+ }
2273
+ refund {
2274
+ id
2275
+ paymentId
2276
+ total
2277
+ }
2278
+ surcharges {
2279
+ id
2280
+ }
2281
+ }
2282
+ }
2283
+ ${DISCOUNT_FRAGMENT}
2284
+ ${ORDER_ADDRESS_FRAGMENT}
2285
+ ${FULFILLMENT_FRAGMENT}
2286
+ ${ORDER_LINE_FRAGMENT}
2286
2287
  `;
2287
- const GET_ORDERS_LIST = gql `
2288
- query GetOrderList($options: OrderListOptions) {
2289
- orders(options: $options) {
2290
- items {
2291
- ...Order
2292
- }
2293
- totalItems
2294
- }
2295
- }
2296
- ${ORDER_FRAGMENT}
2288
+ const GET_ORDERS_LIST = gql `
2289
+ query GetOrderList($options: OrderListOptions) {
2290
+ orders(options: $options) {
2291
+ items {
2292
+ ...Order
2293
+ }
2294
+ totalItems
2295
+ }
2296
+ }
2297
+ ${ORDER_FRAGMENT}
2297
2298
  `;
2298
- const GET_ORDER = gql `
2299
- query GetOrder($id: ID!) {
2300
- order(id: $id) {
2301
- ...OrderDetail
2302
- }
2303
- }
2304
- ${ORDER_DETAIL_FRAGMENT}
2299
+ const GET_ORDER = gql `
2300
+ query GetOrder($id: ID!) {
2301
+ order(id: $id) {
2302
+ ...OrderDetail
2303
+ }
2304
+ }
2305
+ ${ORDER_DETAIL_FRAGMENT}
2305
2306
  `;
2306
- const SETTLE_PAYMENT = gql `
2307
- mutation SettlePayment($id: ID!) {
2308
- settlePayment(id: $id) {
2309
- ... on Payment {
2310
- id
2311
- transactionId
2312
- amount
2313
- method
2314
- state
2315
- metadata
2316
- }
2317
- ...ErrorResult
2318
- ... on SettlePaymentError {
2319
- paymentErrorMessage
2320
- }
2321
- ... on PaymentStateTransitionError {
2322
- transitionError
2323
- }
2324
- ... on OrderStateTransitionError {
2325
- transitionError
2326
- }
2327
- }
2328
- }
2329
- ${ERROR_RESULT_FRAGMENT}
2307
+ const SETTLE_PAYMENT = gql `
2308
+ mutation SettlePayment($id: ID!) {
2309
+ settlePayment(id: $id) {
2310
+ ... on Payment {
2311
+ id
2312
+ transactionId
2313
+ amount
2314
+ method
2315
+ state
2316
+ metadata
2317
+ }
2318
+ ...ErrorResult
2319
+ ... on SettlePaymentError {
2320
+ paymentErrorMessage
2321
+ }
2322
+ ... on PaymentStateTransitionError {
2323
+ transitionError
2324
+ }
2325
+ ... on OrderStateTransitionError {
2326
+ transitionError
2327
+ }
2328
+ }
2329
+ }
2330
+ ${ERROR_RESULT_FRAGMENT}
2330
2331
  `;
2331
- const TRANSITION_PAYMENT_TO_STATE = gql `
2332
- mutation TransitionPaymentToState($id: ID!, $state: String!) {
2333
- transitionPaymentToState(id: $id, state: $state) {
2334
- ... on Payment {
2335
- id
2336
- transactionId
2337
- amount
2338
- method
2339
- state
2340
- metadata
2341
- }
2342
- ...ErrorResult
2343
- ... on PaymentStateTransitionError {
2344
- transitionError
2345
- }
2346
- }
2347
- }
2348
- ${ERROR_RESULT_FRAGMENT}
2332
+ const TRANSITION_PAYMENT_TO_STATE = gql `
2333
+ mutation TransitionPaymentToState($id: ID!, $state: String!) {
2334
+ transitionPaymentToState(id: $id, state: $state) {
2335
+ ... on Payment {
2336
+ id
2337
+ transactionId
2338
+ amount
2339
+ method
2340
+ state
2341
+ metadata
2342
+ }
2343
+ ...ErrorResult
2344
+ ... on PaymentStateTransitionError {
2345
+ transitionError
2346
+ }
2347
+ }
2348
+ }
2349
+ ${ERROR_RESULT_FRAGMENT}
2349
2350
  `;
2350
- const CREATE_FULFILLMENT = gql `
2351
- mutation CreateFulfillment($input: FulfillOrderInput!) {
2352
- addFulfillmentToOrder(input: $input) {
2353
- ...Fulfillment
2354
- ... on CreateFulfillmentError {
2355
- errorCode
2356
- message
2357
- fulfillmentHandlerError
2358
- }
2359
- ... on FulfillmentStateTransitionError {
2360
- errorCode
2361
- message
2362
- transitionError
2363
- }
2364
- ...ErrorResult
2365
- }
2366
- }
2367
- ${FULFILLMENT_FRAGMENT}
2368
- ${ERROR_RESULT_FRAGMENT}
2351
+ const CREATE_FULFILLMENT = gql `
2352
+ mutation CreateFulfillment($input: FulfillOrderInput!) {
2353
+ addFulfillmentToOrder(input: $input) {
2354
+ ...Fulfillment
2355
+ ... on CreateFulfillmentError {
2356
+ errorCode
2357
+ message
2358
+ fulfillmentHandlerError
2359
+ }
2360
+ ... on FulfillmentStateTransitionError {
2361
+ errorCode
2362
+ message
2363
+ transitionError
2364
+ }
2365
+ ...ErrorResult
2366
+ }
2367
+ }
2368
+ ${FULFILLMENT_FRAGMENT}
2369
+ ${ERROR_RESULT_FRAGMENT}
2369
2370
  `;
2370
- const CANCEL_ORDER = gql `
2371
- mutation CancelOrder($input: CancelOrderInput!) {
2372
- cancelOrder(input: $input) {
2373
- ...OrderDetail
2374
- ...ErrorResult
2375
- }
2376
- }
2377
- ${ORDER_DETAIL_FRAGMENT}
2378
- ${ERROR_RESULT_FRAGMENT}
2371
+ const CANCEL_ORDER = gql `
2372
+ mutation CancelOrder($input: CancelOrderInput!) {
2373
+ cancelOrder(input: $input) {
2374
+ ...OrderDetail
2375
+ ...ErrorResult
2376
+ }
2377
+ }
2378
+ ${ORDER_DETAIL_FRAGMENT}
2379
+ ${ERROR_RESULT_FRAGMENT}
2379
2380
  `;
2380
- const REFUND_ORDER = gql `
2381
- mutation RefundOrder($input: RefundOrderInput!) {
2382
- refundOrder(input: $input) {
2383
- ...Refund
2384
- ...ErrorResult
2385
- }
2386
- }
2387
- ${REFUND_FRAGMENT}
2388
- ${ERROR_RESULT_FRAGMENT}
2381
+ const REFUND_ORDER = gql `
2382
+ mutation RefundOrder($input: RefundOrderInput!) {
2383
+ refundOrder(input: $input) {
2384
+ ...Refund
2385
+ ...ErrorResult
2386
+ }
2387
+ }
2388
+ ${REFUND_FRAGMENT}
2389
+ ${ERROR_RESULT_FRAGMENT}
2389
2390
  `;
2390
- const SETTLE_REFUND = gql `
2391
- mutation SettleRefund($input: SettleRefundInput!) {
2392
- settleRefund(input: $input) {
2393
- ...Refund
2394
- ...ErrorResult
2395
- }
2396
- }
2397
- ${REFUND_FRAGMENT}
2398
- ${ERROR_RESULT_FRAGMENT}
2391
+ const SETTLE_REFUND = gql `
2392
+ mutation SettleRefund($input: SettleRefundInput!) {
2393
+ settleRefund(input: $input) {
2394
+ ...Refund
2395
+ ...ErrorResult
2396
+ }
2397
+ }
2398
+ ${REFUND_FRAGMENT}
2399
+ ${ERROR_RESULT_FRAGMENT}
2399
2400
  `;
2400
- const GET_ORDER_HISTORY = gql `
2401
- query GetOrderHistory($id: ID!, $options: HistoryEntryListOptions) {
2402
- order(id: $id) {
2403
- id
2404
- history(options: $options) {
2405
- totalItems
2406
- items {
2407
- id
2408
- type
2409
- createdAt
2410
- isPublic
2411
- administrator {
2412
- id
2413
- firstName
2414
- lastName
2415
- }
2416
- data
2417
- }
2418
- }
2419
- }
2420
- }
2401
+ const GET_ORDER_HISTORY = gql `
2402
+ query GetOrderHistory($id: ID!, $options: HistoryEntryListOptions) {
2403
+ order(id: $id) {
2404
+ id
2405
+ history(options: $options) {
2406
+ totalItems
2407
+ items {
2408
+ id
2409
+ type
2410
+ createdAt
2411
+ isPublic
2412
+ administrator {
2413
+ id
2414
+ firstName
2415
+ lastName
2416
+ }
2417
+ data
2418
+ }
2419
+ }
2420
+ }
2421
+ }
2421
2422
  `;
2422
- const ADD_NOTE_TO_ORDER = gql `
2423
- mutation AddNoteToOrder($input: AddNoteToOrderInput!) {
2424
- addNoteToOrder(input: $input) {
2425
- id
2426
- }
2427
- }
2423
+ const ADD_NOTE_TO_ORDER = gql `
2424
+ mutation AddNoteToOrder($input: AddNoteToOrderInput!) {
2425
+ addNoteToOrder(input: $input) {
2426
+ id
2427
+ }
2428
+ }
2428
2429
  `;
2429
- const UPDATE_ORDER_NOTE = gql `
2430
- mutation UpdateOrderNote($input: UpdateOrderNoteInput!) {
2431
- updateOrderNote(input: $input) {
2432
- id
2433
- data
2434
- isPublic
2435
- }
2436
- }
2430
+ const UPDATE_ORDER_NOTE = gql `
2431
+ mutation UpdateOrderNote($input: UpdateOrderNoteInput!) {
2432
+ updateOrderNote(input: $input) {
2433
+ id
2434
+ data
2435
+ isPublic
2436
+ }
2437
+ }
2437
2438
  `;
2438
- const DELETE_ORDER_NOTE = gql `
2439
- mutation DeleteOrderNote($id: ID!) {
2440
- deleteOrderNote(id: $id) {
2441
- result
2442
- message
2443
- }
2444
- }
2439
+ const DELETE_ORDER_NOTE = gql `
2440
+ mutation DeleteOrderNote($id: ID!) {
2441
+ deleteOrderNote(id: $id) {
2442
+ result
2443
+ message
2444
+ }
2445
+ }
2445
2446
  `;
2446
- const TRANSITION_ORDER_TO_STATE = gql `
2447
- mutation TransitionOrderToState($id: ID!, $state: String!) {
2448
- transitionOrderToState(id: $id, state: $state) {
2449
- ...Order
2450
- ...ErrorResult
2451
- ... on OrderStateTransitionError {
2452
- transitionError
2453
- }
2454
- }
2455
- }
2456
- ${ORDER_FRAGMENT}
2457
- ${ERROR_RESULT_FRAGMENT}
2447
+ const TRANSITION_ORDER_TO_STATE = gql `
2448
+ mutation TransitionOrderToState($id: ID!, $state: String!) {
2449
+ transitionOrderToState(id: $id, state: $state) {
2450
+ ...Order
2451
+ ...ErrorResult
2452
+ ... on OrderStateTransitionError {
2453
+ transitionError
2454
+ }
2455
+ }
2456
+ }
2457
+ ${ORDER_FRAGMENT}
2458
+ ${ERROR_RESULT_FRAGMENT}
2458
2459
  `;
2459
- const UPDATE_ORDER_CUSTOM_FIELDS = gql `
2460
- mutation UpdateOrderCustomFields($input: UpdateOrderInput!) {
2461
- setOrderCustomFields(input: $input) {
2462
- ...Order
2463
- }
2464
- }
2465
- ${ORDER_FRAGMENT}
2460
+ const UPDATE_ORDER_CUSTOM_FIELDS = gql `
2461
+ mutation UpdateOrderCustomFields($input: UpdateOrderInput!) {
2462
+ setOrderCustomFields(input: $input) {
2463
+ ...Order
2464
+ }
2465
+ }
2466
+ ${ORDER_FRAGMENT}
2466
2467
  `;
2467
- const TRANSITION_FULFILLMENT_TO_STATE = gql `
2468
- mutation TransitionFulfillmentToState($id: ID!, $state: String!) {
2469
- transitionFulfillmentToState(id: $id, state: $state) {
2470
- ...Fulfillment
2471
- ...ErrorResult
2472
- ... on FulfillmentStateTransitionError {
2473
- transitionError
2474
- }
2475
- }
2476
- }
2477
- ${FULFILLMENT_FRAGMENT}
2478
- ${ERROR_RESULT_FRAGMENT}
2468
+ const TRANSITION_FULFILLMENT_TO_STATE = gql `
2469
+ mutation TransitionFulfillmentToState($id: ID!, $state: String!) {
2470
+ transitionFulfillmentToState(id: $id, state: $state) {
2471
+ ...Fulfillment
2472
+ ...ErrorResult
2473
+ ... on FulfillmentStateTransitionError {
2474
+ transitionError
2475
+ }
2476
+ }
2477
+ }
2478
+ ${FULFILLMENT_FRAGMENT}
2479
+ ${ERROR_RESULT_FRAGMENT}
2479
2480
  `;
2480
- const GET_ORDER_SUMMARY = gql `
2481
- query GetOrderSummary($start: DateTime!, $end: DateTime!) {
2482
- orders(options: { filter: { orderPlacedAt: { between: { start: $start, end: $end } } } }) {
2483
- totalItems
2484
- items {
2485
- id
2486
- total
2487
- currencyCode
2488
- }
2489
- }
2490
- }
2481
+ const GET_ORDER_SUMMARY = gql `
2482
+ query GetOrderSummary($start: DateTime!, $end: DateTime!) {
2483
+ orders(options: { filter: { orderPlacedAt: { between: { start: $start, end: $end } } } }) {
2484
+ totalItems
2485
+ items {
2486
+ id
2487
+ total
2488
+ currencyCode
2489
+ }
2490
+ }
2491
+ }
2491
2492
  `;
2492
- const MODIFY_ORDER = gql `
2493
- mutation ModifyOrder($input: ModifyOrderInput!) {
2494
- modifyOrder(input: $input) {
2495
- ...OrderDetail
2496
- ...ErrorResult
2497
- }
2498
- }
2499
- ${ORDER_DETAIL_FRAGMENT}
2500
- ${ERROR_RESULT_FRAGMENT}
2493
+ const MODIFY_ORDER = gql `
2494
+ mutation ModifyOrder($input: ModifyOrderInput!) {
2495
+ modifyOrder(input: $input) {
2496
+ ...OrderDetail
2497
+ ...ErrorResult
2498
+ }
2499
+ }
2500
+ ${ORDER_DETAIL_FRAGMENT}
2501
+ ${ERROR_RESULT_FRAGMENT}
2501
2502
  `;
2502
- const ADD_MANUAL_PAYMENT_TO_ORDER = gql `
2503
- mutation AddManualPayment($input: ManualPaymentInput!) {
2504
- addManualPaymentToOrder(input: $input) {
2505
- ...OrderDetail
2506
- ...ErrorResult
2507
- }
2508
- }
2509
- ${ORDER_DETAIL_FRAGMENT}
2510
- ${ERROR_RESULT_FRAGMENT}
2503
+ const ADD_MANUAL_PAYMENT_TO_ORDER = gql `
2504
+ mutation AddManualPayment($input: ManualPaymentInput!) {
2505
+ addManualPaymentToOrder(input: $input) {
2506
+ ...OrderDetail
2507
+ ...ErrorResult
2508
+ }
2509
+ }
2510
+ ${ORDER_DETAIL_FRAGMENT}
2511
+ ${ERROR_RESULT_FRAGMENT}
2511
2512
  `;
2512
2513
 
2513
2514
  class OrderDataService {
@@ -8222,6 +8223,7 @@ class AppShellComponent {
8222
8223
  this.modalService = modalService;
8223
8224
  this.localStorageService = localStorageService;
8224
8225
  this.availableLanguages = [];
8226
+ this.hideVendureBranding = getAppConfig().hideVendureBranding;
8225
8227
  }
8226
8228
  ngOnInit() {
8227
8229
  this.userName$ = this.dataService.client
@@ -8265,10 +8267,10 @@ class AppShellComponent {
8265
8267
  }
8266
8268
  }
8267
8269
  AppShellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AppShellComponent, deps: [{ token: AuthService }, { token: DataService }, { token: i1$2.Router }, { token: I18nService }, { token: ModalService }, { token: LocalStorageService }], target: i0.ɵɵFactoryTarget.Component });
8268
- AppShellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: AppShellComponent, selector: "vdr-app-shell", ngImport: i0, template: "<clr-main-container>\r\n <clr-header>\r\n <div class=\"branding\">\r\n <a [routerLink]=\"['/']\"><img src=\"assets/logo-75px.png\" class=\"logo\" /></a>\r\n </div>\r\n <div class=\"header-nav\"></div>\r\n <div class=\"header-actions\">\r\n <vdr-channel-switcher *vdrIfMultichannel></vdr-channel-switcher>\r\n <vdr-user-menu [userName]=\"userName$ | async\"\r\n [uiLanguageAndLocale]=\"uiLanguageAndLocale$ | async\"\r\n [availableLanguages]=\"availableLanguages\"\r\n (selectUiLanguage)=\"selectUiLanguage()\"\r\n (logOut)=\"logOut()\"></vdr-user-menu>\r\n </div>\r\n </clr-header>\r\n <nav class=\"subnav\"><vdr-breadcrumb></vdr-breadcrumb></nav>\r\n\r\n <div class=\"content-container\">\r\n <div class=\"content-area\"><router-outlet></router-outlet></div>\r\n <vdr-main-nav></vdr-main-nav>\r\n </div>\r\n</clr-main-container>\r\n", styles: [".branding{min-width:0}.logo{width:60px}@media screen and (min-width: 768px){vdr-breadcrumb{margin-left:10.8rem}}.header-actions{align-items:center}.content-area{position:relative}\n"], components: [{ type: i1$3.ClrHeader, selector: "clr-header" }, { type: ChannelSwitcherComponent, selector: "vdr-channel-switcher" }, { type: UserMenuComponent, selector: "vdr-user-menu", inputs: ["userName", "availableLanguages", "uiLanguageAndLocale"], outputs: ["logOut", "selectUiLanguage"] }, { type: BreadcrumbComponent, selector: "vdr-breadcrumb" }, { type: MainNavComponent, selector: "vdr-main-nav" }], directives: [{ type: i1$3.ClrMainContainer, selector: "clr-main-container" }, { type: i1$3.MainContainerWillyWonka, selector: "clr-main-container" }, { type: i1$3.NavDetectionOompaLoompa, selector: "clr-header" }, { type: i1$2.RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "preserveFragment", "skipLocationChange", "replaceUrl", "state", "relativeTo", "routerLink"] }, { type: IfMultichannelDirective, selector: "[vdrIfMultichannel]", inputs: ["vdrIfMultichannelElse"] }, { type: i1$2.RouterOutlet, selector: "router-outlet", outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], pipes: { "async": i3.AsyncPipe } });
8270
+ AppShellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: AppShellComponent, selector: "vdr-app-shell", ngImport: i0, template: "<clr-main-container>\r\n <clr-header>\r\n <div class=\"branding\">\r\n <a [routerLink]=\"['/']\"><img src=\"assets/logo-75px.png\" class=\"logo\" /><span class=\"wordmark\" *ngIf=\"!hideVendureBranding\">vendure</span></a>\r\n </div>\r\n <div class=\"header-nav\"></div>\r\n <div class=\"header-actions\">\r\n <vdr-channel-switcher *vdrIfMultichannel></vdr-channel-switcher>\r\n <vdr-user-menu [userName]=\"userName$ | async\"\r\n [uiLanguageAndLocale]=\"uiLanguageAndLocale$ | async\"\r\n [availableLanguages]=\"availableLanguages\"\r\n (selectUiLanguage)=\"selectUiLanguage()\"\r\n (logOut)=\"logOut()\"></vdr-user-menu>\r\n </div>\r\n </clr-header>\r\n <nav class=\"subnav\"><vdr-breadcrumb></vdr-breadcrumb></nav>\r\n\r\n <div class=\"content-container\">\r\n <div class=\"content-area\"><router-outlet></router-outlet></div>\r\n <vdr-main-nav></vdr-main-nav>\r\n </div>\r\n</clr-main-container>\r\n", styles: [".branding{min-width:0}.logo{width:40px}.wordmark{font-weight:700;margin-left:12px;font-size:24px;color:var(--color-primary-500)}@media screen and (min-width: 768px){vdr-breadcrumb{margin-left:10.8rem}}.header-actions{align-items:center}.content-area{position:relative}::ng-deep .header{background-image:linear-gradient(to right,var(--color-header-gradient-from),var(--color-header-gradient-to))}\n"], components: [{ type: i1$3.ClrHeader, selector: "clr-header" }, { type: ChannelSwitcherComponent, selector: "vdr-channel-switcher" }, { type: UserMenuComponent, selector: "vdr-user-menu", inputs: ["userName", "availableLanguages", "uiLanguageAndLocale"], outputs: ["logOut", "selectUiLanguage"] }, { type: BreadcrumbComponent, selector: "vdr-breadcrumb" }, { type: MainNavComponent, selector: "vdr-main-nav" }], directives: [{ type: i1$3.ClrMainContainer, selector: "clr-main-container" }, { type: i1$3.MainContainerWillyWonka, selector: "clr-main-container" }, { type: i1$3.NavDetectionOompaLoompa, selector: "clr-header" }, { type: i1$2.RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "preserveFragment", "skipLocationChange", "replaceUrl", "state", "relativeTo", "routerLink"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: IfMultichannelDirective, selector: "[vdrIfMultichannel]", inputs: ["vdrIfMultichannelElse"] }, { type: i1$2.RouterOutlet, selector: "router-outlet", outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], pipes: { "async": i3.AsyncPipe } });
8269
8271
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AppShellComponent, decorators: [{
8270
8272
  type: Component,
8271
- args: [{ selector: 'vdr-app-shell', template: "<clr-main-container>\r\n <clr-header>\r\n <div class=\"branding\">\r\n <a [routerLink]=\"['/']\"><img src=\"assets/logo-75px.png\" class=\"logo\" /></a>\r\n </div>\r\n <div class=\"header-nav\"></div>\r\n <div class=\"header-actions\">\r\n <vdr-channel-switcher *vdrIfMultichannel></vdr-channel-switcher>\r\n <vdr-user-menu [userName]=\"userName$ | async\"\r\n [uiLanguageAndLocale]=\"uiLanguageAndLocale$ | async\"\r\n [availableLanguages]=\"availableLanguages\"\r\n (selectUiLanguage)=\"selectUiLanguage()\"\r\n (logOut)=\"logOut()\"></vdr-user-menu>\r\n </div>\r\n </clr-header>\r\n <nav class=\"subnav\"><vdr-breadcrumb></vdr-breadcrumb></nav>\r\n\r\n <div class=\"content-container\">\r\n <div class=\"content-area\"><router-outlet></router-outlet></div>\r\n <vdr-main-nav></vdr-main-nav>\r\n </div>\r\n</clr-main-container>\r\n", styles: [".branding{min-width:0}.logo{width:60px}@media screen and (min-width: 768px){vdr-breadcrumb{margin-left:10.8rem}}.header-actions{align-items:center}.content-area{position:relative}\n"] }]
8273
+ args: [{ selector: 'vdr-app-shell', template: "<clr-main-container>\r\n <clr-header>\r\n <div class=\"branding\">\r\n <a [routerLink]=\"['/']\"><img src=\"assets/logo-75px.png\" class=\"logo\" /><span class=\"wordmark\" *ngIf=\"!hideVendureBranding\">vendure</span></a>\r\n </div>\r\n <div class=\"header-nav\"></div>\r\n <div class=\"header-actions\">\r\n <vdr-channel-switcher *vdrIfMultichannel></vdr-channel-switcher>\r\n <vdr-user-menu [userName]=\"userName$ | async\"\r\n [uiLanguageAndLocale]=\"uiLanguageAndLocale$ | async\"\r\n [availableLanguages]=\"availableLanguages\"\r\n (selectUiLanguage)=\"selectUiLanguage()\"\r\n (logOut)=\"logOut()\"></vdr-user-menu>\r\n </div>\r\n </clr-header>\r\n <nav class=\"subnav\"><vdr-breadcrumb></vdr-breadcrumb></nav>\r\n\r\n <div class=\"content-container\">\r\n <div class=\"content-area\"><router-outlet></router-outlet></div>\r\n <vdr-main-nav></vdr-main-nav>\r\n </div>\r\n</clr-main-container>\r\n", styles: [".branding{min-width:0}.logo{width:40px}.wordmark{font-weight:700;margin-left:12px;font-size:24px;color:var(--color-primary-500)}@media screen and (min-width: 768px){vdr-breadcrumb{margin-left:10.8rem}}.header-actions{align-items:center}.content-area{position:relative}::ng-deep .header{background-image:linear-gradient(to right,var(--color-header-gradient-from),var(--color-header-gradient-to))}\n"] }]
8272
8274
  }], ctorParameters: function () { return [{ type: AuthService }, { type: DataService }, { type: i1$2.Router }, { type: I18nService }, { type: ModalService }, { type: LocalStorageService }]; } });
8273
8275
 
8274
8276
  class NotificationComponent {
@@ -9524,52 +9526,658 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImpor
9524
9526
  }] } });
9525
9527
 
9526
9528
  /**
9527
- * A wrapper around an <input> element which adds a prefix and/or a suffix element.
9529
+ * ConfigArg values are always stored as strings. If they are not primitives, then
9530
+ * they are JSON-encoded. This function unwraps them back into their original
9531
+ * data type.
9528
9532
  */
9529
- class AffixedInputComponent {
9533
+ function getConfigArgValue(value) {
9534
+ try {
9535
+ return value ? JSON.parse(value) : undefined;
9536
+ }
9537
+ catch (e) {
9538
+ return value;
9539
+ }
9540
+ }
9541
+ function encodeConfigArgValue(value) {
9542
+ return Array.isArray(value) ? JSON.stringify(value) : (value !== null && value !== void 0 ? value : '').toString();
9530
9543
  }
9531
- AffixedInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AffixedInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9532
- AffixedInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: AffixedInputComponent, selector: "vdr-affixed-input", inputs: { prefix: "prefix", suffix: "suffix" }, ngImport: i0, template: "<div [class.has-prefix]=\"!!prefix\" [class.has-suffix]=\"!!suffix\">\r\n <ng-content></ng-content>\r\n</div>\r\n<div class=\"affix prefix\" *ngIf=\"prefix\">{{ prefix }}</div>\r\n<div class=\"affix suffix\" *ngIf=\"suffix\">{{ suffix }}</div>\r\n", styles: [":host{display:inline-flex}.affix{color:var(--color-grey-800);display:flex;align-items:center;background-color:var(--color-grey-200);border:1px solid var(--color-component-border-300);top:1px;padding:3px;line-height:.58333rem;transition:border .2s}::ng-deep .has-prefix input{border-top-left-radius:0!important;border-bottom-left-radius:0!important}.prefix{order:-1;border-radius:3px 0 0 3px;border-right:none}::ng-deep .has-suffix input{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.suffix{border-radius:0 3px 3px 0;border-left:none}\n"], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9533
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AffixedInputComponent, decorators: [{
9534
- type: Component,
9535
- args: [{ selector: 'vdr-affixed-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class.has-prefix]=\"!!prefix\" [class.has-suffix]=\"!!suffix\">\r\n <ng-content></ng-content>\r\n</div>\r\n<div class=\"affix prefix\" *ngIf=\"prefix\">{{ prefix }}</div>\r\n<div class=\"affix suffix\" *ngIf=\"suffix\">{{ suffix }}</div>\r\n", styles: [":host{display:inline-flex}.affix{color:var(--color-grey-800);display:flex;align-items:center;background-color:var(--color-grey-200);border:1px solid var(--color-component-border-300);top:1px;padding:3px;line-height:.58333rem;transition:border .2s}::ng-deep .has-prefix input{border-top-left-radius:0!important;border-bottom-left-radius:0!important}.prefix{order:-1;border-radius:3px 0 0 3px;border-right:none}::ng-deep .has-suffix input{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.suffix{border-radius:0 3px 3px 0;border-left:none}\n"] }]
9536
- }], propDecorators: { prefix: [{
9537
- type: Input
9538
- }], suffix: [{
9539
- type: Input
9540
- }] } });
9541
-
9542
9544
  /**
9543
- * @description
9544
- * A form input control which displays currency in decimal format, whilst working
9545
- * with the integer cent value in the background.
9546
- *
9547
- * @example
9548
- * ```HTML
9549
- * <vdr-currency-input
9550
- * [(ngModel)]="entityPrice"
9551
- * [currencyCode]="currencyCode"
9552
- * ></vdr-currency-input>
9553
- * ```
9554
- *
9555
- * @docsCategory components
9545
+ * Creates an empty ConfigurableOperation object based on the definition.
9556
9546
  */
9557
- class CurrencyInputComponent {
9558
- constructor(dataService, changeDetectorRef) {
9559
- this.dataService = dataService;
9560
- this.changeDetectorRef = changeDetectorRef;
9561
- this.disabled = false;
9562
- this.readonly = false;
9563
- this.currencyCode = '';
9564
- this.valueChange = new EventEmitter();
9565
- this.hasFractionPart = true;
9566
- this.currencyCode$ = new BehaviorSubject('');
9567
- }
9568
- ngOnInit() {
9569
- const languageCode$ = this.dataService.client.uiState().mapStream(data => data.uiState.language);
9570
- const shouldPrefix$ = combineLatest(languageCode$, this.currencyCode$).pipe(map(([languageCode, currencyCode]) => {
9571
- var _a, _b;
9572
- if (!currencyCode) {
9547
+ function configurableDefinitionToInstance(def) {
9548
+ return Object.assign(Object.assign({}, def), { args: def.args.map(arg => {
9549
+ return Object.assign(Object.assign({}, arg), { value: getDefaultConfigArgValue(arg) });
9550
+ }) });
9551
+ }
9552
+ /**
9553
+ * Converts an object of the type:
9554
+ * ```
9555
+ * {
9556
+ * code: 'my-operation',
9557
+ * args: {
9558
+ * someProperty: 'foo'
9559
+ * }
9560
+ * }
9561
+ * ```
9562
+ * to the format defined by the ConfigurableOperationInput GraphQL input type:
9563
+ * ```
9564
+ * {
9565
+ * code: 'my-operation',
9566
+ * args: [
9567
+ * { name: 'someProperty', value: 'foo' }
9568
+ * ]
9569
+ * }
9570
+ * ```
9571
+ */
9572
+ function toConfigurableOperationInput(operation, formValueOperations) {
9573
+ return {
9574
+ code: operation.code,
9575
+ arguments: Object.values(formValueOperations.args || {}).map((value, j) => ({
9576
+ name: operation.args[j].name,
9577
+ value: (value === null || value === void 0 ? void 0 : value.hasOwnProperty('value'))
9578
+ ? encodeConfigArgValue(value.value)
9579
+ : encodeConfigArgValue(value),
9580
+ })),
9581
+ };
9582
+ }
9583
+ function configurableOperationValueIsValid(def, value) {
9584
+ if (!def || !value) {
9585
+ return false;
9586
+ }
9587
+ if (def.code !== value.code) {
9588
+ return false;
9589
+ }
9590
+ for (const argDef of def.args) {
9591
+ const argVal = value.args[argDef.name];
9592
+ if (argDef.required && (argVal == null || argVal === '' || argVal === '0')) {
9593
+ return false;
9594
+ }
9595
+ }
9596
+ return true;
9597
+ }
9598
+ /**
9599
+ * Returns a default value based on the type of the config arg.
9600
+ */
9601
+ function getDefaultConfigArgValue(arg) {
9602
+ if (arg.list) {
9603
+ return [];
9604
+ }
9605
+ if (arg.defaultValue) {
9606
+ return arg.defaultValue;
9607
+ }
9608
+ const type = arg.type;
9609
+ switch (type) {
9610
+ case 'string':
9611
+ case 'datetime':
9612
+ case 'float':
9613
+ case 'ID':
9614
+ case 'int':
9615
+ return null;
9616
+ case 'boolean':
9617
+ return false;
9618
+ default:
9619
+ assertNever(type);
9620
+ }
9621
+ }
9622
+
9623
+ /**
9624
+ * Interpolates the description of an ConfigurableOperation with the given values.
9625
+ */
9626
+ function interpolateDescription(operation, values) {
9627
+ if (!operation) {
9628
+ return '';
9629
+ }
9630
+ const templateString = operation.description;
9631
+ const interpolated = templateString.replace(/{\s*([a-zA-Z0-9]+)\s*}/gi, (substring, argName) => {
9632
+ const normalizedArgName = argName.toLowerCase();
9633
+ const value = values[normalizedArgName];
9634
+ if (value == null) {
9635
+ return '_';
9636
+ }
9637
+ let formatted = value;
9638
+ const argDef = operation.args.find(arg => arg.name === normalizedArgName);
9639
+ if (argDef && argDef.type === 'int' && argDef.ui && argDef.ui.component === 'currency-form-input') {
9640
+ formatted = value / 100;
9641
+ }
9642
+ if (argDef && argDef.type === 'datetime' && value instanceof Date) {
9643
+ formatted = value.toLocaleDateString();
9644
+ }
9645
+ return formatted;
9646
+ });
9647
+ return interpolated;
9648
+ }
9649
+
9650
+ class HelpTooltipComponent {
9651
+ }
9652
+ HelpTooltipComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: HelpTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9653
+ HelpTooltipComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: HelpTooltipComponent, selector: "vdr-help-tooltip", inputs: { content: "content", position: "position" }, ngImport: i0, template: "<clr-tooltip>\r\n <clr-icon clrTooltipTrigger shape=\"help\" size=\"14\"></clr-icon>\r\n <clr-tooltip-content [clrPosition]=\"position\" clrSize=\"md\" *clrIfOpen>\r\n <span>{{ content }}</span>\r\n </clr-tooltip-content>\r\n</clr-tooltip>\r\n", styles: ["clr-tooltip{display:inline-flex}\n"], components: [{ type: i1$3.ClrTooltip, selector: "clr-tooltip" }, { type: i1$3.ClrTooltipContent, selector: "clr-tooltip-content", inputs: ["id", "clrPosition", "clrSize"] }], directives: [{ type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i1$3.ClrTooltipTrigger, selector: "[clrTooltipTrigger]" }, { type: i1$3.ClrIfOpen, selector: "[clrIfOpen]", inputs: ["clrIfOpen"], outputs: ["clrIfOpenChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9654
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: HelpTooltipComponent, decorators: [{
9655
+ type: Component,
9656
+ args: [{ selector: 'vdr-help-tooltip', changeDetection: ChangeDetectionStrategy.OnPush, template: "<clr-tooltip>\r\n <clr-icon clrTooltipTrigger shape=\"help\" size=\"14\"></clr-icon>\r\n <clr-tooltip-content [clrPosition]=\"position\" clrSize=\"md\" *clrIfOpen>\r\n <span>{{ content }}</span>\r\n </clr-tooltip-content>\r\n</clr-tooltip>\r\n", styles: ["clr-tooltip{display:inline-flex}\n"] }]
9657
+ }], propDecorators: { content: [{
9658
+ type: Input
9659
+ }], position: [{
9660
+ type: Input
9661
+ }] } });
9662
+
9663
+ /**
9664
+ * A host component which delegates to an instance or list of FormInputComponent components.
9665
+ */
9666
+ class DynamicFormInputComponent {
9667
+ constructor(componentRegistryService, componentFactoryResolver, changeDetectorRef, injector) {
9668
+ this.componentRegistryService = componentRegistryService;
9669
+ this.componentFactoryResolver = componentFactoryResolver;
9670
+ this.changeDetectorRef = changeDetectorRef;
9671
+ this.injector = injector;
9672
+ this.renderAsList = false;
9673
+ this.listItems = [];
9674
+ this.listId = 1;
9675
+ this.listFormArray = new FormArray([]);
9676
+ this.renderList$ = new Subject();
9677
+ this.destroy$ = new Subject();
9678
+ }
9679
+ ngOnInit() {
9680
+ const componentId = this.getInputComponentConfig(this.def).component;
9681
+ const componentType = this.componentRegistryService.getInputComponent(componentId);
9682
+ if (componentType) {
9683
+ this.componentType = componentType;
9684
+ }
9685
+ else {
9686
+ // tslint:disable-next-line:no-console
9687
+ console.error(`No form input component registered with the id "${componentId}". Using the default input instead.`);
9688
+ const defaultComponentType = this.componentRegistryService.getInputComponent(this.getInputComponentConfig(Object.assign(Object.assign({}, this.def), { ui: undefined })).component);
9689
+ if (defaultComponentType) {
9690
+ this.componentType = defaultComponentType;
9691
+ }
9692
+ }
9693
+ }
9694
+ ngAfterViewInit() {
9695
+ var _a;
9696
+ if (this.componentType) {
9697
+ const factory = this.componentFactoryResolver.resolveComponentFactory(this.componentType);
9698
+ // create a temp instance to check the value of `isListInput`
9699
+ const cmpRef = factory.create(this.injector);
9700
+ const isListInputComponent = (_a = cmpRef.instance.isListInput) !== null && _a !== void 0 ? _a : false;
9701
+ cmpRef.destroy();
9702
+ if (this.def.list === false && isListInputComponent) {
9703
+ throw new Error(`The ${this.componentType.name} component is a list input, but the definition for ${this.def.name} does not expect a list`);
9704
+ }
9705
+ this.renderAsList = this.def.list && !isListInputComponent;
9706
+ if (!this.renderAsList) {
9707
+ this.singleComponentRef = this.renderInputComponent(factory, this.singleViewContainer, this.control);
9708
+ }
9709
+ else {
9710
+ let formArraySub;
9711
+ const renderListInputs = (viewContainerRefs) => {
9712
+ if (viewContainerRefs.length) {
9713
+ if (formArraySub) {
9714
+ formArraySub.unsubscribe();
9715
+ }
9716
+ this.listFormArray = new FormArray([]);
9717
+ this.listItems.forEach(i => { var _a; return (_a = i.componentRef) === null || _a === void 0 ? void 0 : _a.destroy(); });
9718
+ viewContainerRefs.forEach((ref, i) => {
9719
+ var _a;
9720
+ const listItem = (_a = this.listItems) === null || _a === void 0 ? void 0 : _a[i];
9721
+ if (listItem) {
9722
+ this.listFormArray.push(listItem.control);
9723
+ listItem.componentRef = this.renderInputComponent(factory, ref, listItem.control);
9724
+ }
9725
+ });
9726
+ formArraySub = this.listFormArray.valueChanges
9727
+ .pipe(takeUntil(this.destroy$))
9728
+ .subscribe(val => {
9729
+ this.control.markAsTouched();
9730
+ this.control.markAsDirty();
9731
+ this.onChange(val);
9732
+ this.control.patchValue(val, { emitEvent: false });
9733
+ });
9734
+ setTimeout(() => this.changeDetectorRef.markForCheck());
9735
+ }
9736
+ };
9737
+ // initial render
9738
+ this.listItemContainers.changes
9739
+ .pipe(take(1))
9740
+ .subscribe(val => renderListInputs(this.listItemContainers));
9741
+ // render on changes to the list
9742
+ this.renderList$
9743
+ .pipe(switchMap(() => this.listItemContainers.changes.pipe(take(1))), takeUntil(this.destroy$))
9744
+ .subscribe(() => {
9745
+ renderListInputs(this.listItemContainers);
9746
+ });
9747
+ }
9748
+ }
9749
+ setTimeout(() => this.changeDetectorRef.markForCheck());
9750
+ }
9751
+ ngOnChanges(changes) {
9752
+ if (this.listItems) {
9753
+ for (const item of this.listItems) {
9754
+ if (item.componentRef) {
9755
+ this.updateBindings(changes, item.componentRef);
9756
+ }
9757
+ }
9758
+ }
9759
+ if (this.singleComponentRef) {
9760
+ this.updateBindings(changes, this.singleComponentRef);
9761
+ }
9762
+ }
9763
+ ngOnDestroy() {
9764
+ this.destroy$.next();
9765
+ this.destroy$.complete();
9766
+ }
9767
+ updateBindings(changes, componentRef) {
9768
+ if ('def' in changes) {
9769
+ componentRef.instance.config = simpleDeepClone(this.def);
9770
+ }
9771
+ if ('readonly' in changes) {
9772
+ componentRef.instance.readonly = this.readonly;
9773
+ }
9774
+ componentRef.injector.get(ChangeDetectorRef).markForCheck();
9775
+ }
9776
+ trackById(index, item) {
9777
+ return item.id;
9778
+ }
9779
+ addListItem() {
9780
+ var _a;
9781
+ if (!this.listItems) {
9782
+ this.listItems = [];
9783
+ }
9784
+ this.listItems.push({
9785
+ id: this.listId++,
9786
+ control: new FormControl((_a = this.def.defaultValue) !== null && _a !== void 0 ? _a : null),
9787
+ });
9788
+ this.renderList$.next();
9789
+ }
9790
+ moveListItem(event) {
9791
+ if (this.listItems) {
9792
+ moveItemInArray(this.listItems, event.previousIndex, event.currentIndex);
9793
+ this.listFormArray.removeAt(event.previousIndex);
9794
+ this.listFormArray.insert(event.currentIndex, event.item.data.control);
9795
+ this.renderList$.next();
9796
+ }
9797
+ }
9798
+ removeListItem(item) {
9799
+ var _a;
9800
+ if (this.listItems) {
9801
+ const index = this.listItems.findIndex(i => i === item);
9802
+ (_a = item.componentRef) === null || _a === void 0 ? void 0 : _a.destroy();
9803
+ this.listFormArray.removeAt(index);
9804
+ this.listItems = this.listItems.filter(i => i !== item);
9805
+ this.renderList$.next();
9806
+ }
9807
+ }
9808
+ renderInputComponent(factory, viewContainerRef, formControl) {
9809
+ const componentRef = viewContainerRef.createComponent(factory);
9810
+ const { instance } = componentRef;
9811
+ instance.config = simpleDeepClone(this.def);
9812
+ instance.formControl = formControl;
9813
+ instance.readonly = this.readonly;
9814
+ componentRef.injector.get(ChangeDetectorRef).markForCheck();
9815
+ return componentRef;
9816
+ }
9817
+ registerOnChange(fn) {
9818
+ this.onChange = fn;
9819
+ }
9820
+ registerOnTouched(fn) {
9821
+ this.onTouch = fn;
9822
+ }
9823
+ writeValue(obj) {
9824
+ if (Array.isArray(obj)) {
9825
+ if (obj.length === this.listItems.length) {
9826
+ obj.forEach((value, index) => {
9827
+ var _a;
9828
+ const control = (_a = this.listItems[index]) === null || _a === void 0 ? void 0 : _a.control;
9829
+ control.patchValue(getConfigArgValue(value), { emitEvent: false });
9830
+ });
9831
+ }
9832
+ else {
9833
+ this.listItems = obj.map(value => ({
9834
+ id: this.listId++,
9835
+ control: new FormControl(getConfigArgValue(value)),
9836
+ }));
9837
+ this.renderList$.next();
9838
+ }
9839
+ }
9840
+ else {
9841
+ this.listItems = [];
9842
+ this.renderList$.next();
9843
+ }
9844
+ this.changeDetectorRef.markForCheck();
9845
+ }
9846
+ getInputComponentConfig(argDef) {
9847
+ var _a;
9848
+ if (this.hasUiConfig(argDef) && argDef.ui.component) {
9849
+ return argDef.ui;
9850
+ }
9851
+ const type = argDef === null || argDef === void 0 ? void 0 : argDef.type;
9852
+ switch (type) {
9853
+ case 'string':
9854
+ case 'localeString': {
9855
+ const hasOptions = !!(this.isConfigArgDef(argDef) && ((_a = argDef.ui) === null || _a === void 0 ? void 0 : _a.options)) ||
9856
+ !!argDef.options;
9857
+ if (hasOptions) {
9858
+ return { component: 'select-form-input' };
9859
+ }
9860
+ else {
9861
+ return { component: 'text-form-input' };
9862
+ }
9863
+ }
9864
+ case 'text': {
9865
+ return { component: 'textarea-form-input' };
9866
+ }
9867
+ case 'int':
9868
+ case 'float':
9869
+ return { component: 'number-form-input' };
9870
+ case 'boolean':
9871
+ return { component: 'boolean-form-input' };
9872
+ case 'datetime':
9873
+ return { component: 'date-form-input' };
9874
+ case 'ID':
9875
+ return { component: 'text-form-input' };
9876
+ case 'relation':
9877
+ return { component: 'relation-form-input' };
9878
+ default:
9879
+ assertNever(type);
9880
+ }
9881
+ }
9882
+ isConfigArgDef(def) {
9883
+ return (def === null || def === void 0 ? void 0 : def.__typename) === 'ConfigArgDefinition';
9884
+ }
9885
+ hasUiConfig(def) {
9886
+ var _a;
9887
+ return typeof def === 'object' && typeof ((_a = def === null || def === void 0 ? void 0 : def.ui) === null || _a === void 0 ? void 0 : _a.component) === 'string';
9888
+ }
9889
+ }
9890
+ DynamicFormInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: DynamicFormInputComponent, deps: [{ token: ComponentRegistryService }, { token: i0.ComponentFactoryResolver }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
9891
+ DynamicFormInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: DynamicFormInputComponent, selector: "vdr-dynamic-form-input", inputs: { def: "def", readonly: "readonly", control: "control" }, providers: [
9892
+ {
9893
+ provide: NG_VALUE_ACCESSOR,
9894
+ useExisting: DynamicFormInputComponent,
9895
+ multi: true,
9896
+ },
9897
+ ], viewQueries: [{ propertyName: "singleViewContainer", first: true, predicate: ["single"], descendants: true, read: ViewContainerRef }, { propertyName: "listItemContainers", predicate: ["listItem"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"!renderAsList; else list\">\r\n <ng-container #single></ng-container>\r\n</ng-container>\r\n<ng-template #list>\r\n <div class=\"list-container\" cdkDropList (cdkDropListDropped)=\"moveListItem($event)\">\r\n <div class=\"list-item-row\" *ngFor=\"let item of listItems; trackBy: trackById\" cdkDrag [cdkDragData]=\"item\">\r\n <ng-container #listItem></ng-container>\r\n <button class=\"btn btn-link btn-sm btn-warning\" (click)=\"removeListItem(item)\" [title]=\"'common.remove-item-from-list' | translate\">\r\n <clr-icon shape=\"times\"></clr-icon>\r\n </button>\r\n <div class=\"flex-spacer\"></div>\r\n <div class=\"drag-handle\" cdkDragHandle *ngIf=\"!readonly\">\r\n <clr-icon shape=\"drag-handle\" size=\"24\"></clr-icon>\r\n </div>\r\n </div>\r\n <button class=\"btn btn-secondary btn-sm\" (click)=\"addListItem()\">\r\n <clr-icon shape=\"plus\"></clr-icon> {{ 'common.add-item-to-list' | translate }}\r\n </button>\r\n </div>\r\n</ng-template>\r\n", styles: [":host{flex:1}.list-container{border:1px solid var(--color-component-border-200);border-radius:3px;padding:12px}.list-item-row{font-size:13px;display:flex;align-items:center;margin:3px 0}.drag-placeholder{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-preview{font-size:13px;background-color:var(--color-component-bg-100);opacity:.8;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:.1}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .list-item-row:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3$1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$3.ClrDatagridItemsTrackBy, selector: "[ngForTrackBy]", inputs: ["ngForTrackBy"] }, { type: i3$1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i3$1.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }], pipes: { "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
9898
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: DynamicFormInputComponent, decorators: [{
9899
+ type: Component,
9900
+ args: [{ selector: 'vdr-dynamic-form-input', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
9901
+ {
9902
+ provide: NG_VALUE_ACCESSOR,
9903
+ useExisting: DynamicFormInputComponent,
9904
+ multi: true,
9905
+ },
9906
+ ], template: "<ng-container *ngIf=\"!renderAsList; else list\">\r\n <ng-container #single></ng-container>\r\n</ng-container>\r\n<ng-template #list>\r\n <div class=\"list-container\" cdkDropList (cdkDropListDropped)=\"moveListItem($event)\">\r\n <div class=\"list-item-row\" *ngFor=\"let item of listItems; trackBy: trackById\" cdkDrag [cdkDragData]=\"item\">\r\n <ng-container #listItem></ng-container>\r\n <button class=\"btn btn-link btn-sm btn-warning\" (click)=\"removeListItem(item)\" [title]=\"'common.remove-item-from-list' | translate\">\r\n <clr-icon shape=\"times\"></clr-icon>\r\n </button>\r\n <div class=\"flex-spacer\"></div>\r\n <div class=\"drag-handle\" cdkDragHandle *ngIf=\"!readonly\">\r\n <clr-icon shape=\"drag-handle\" size=\"24\"></clr-icon>\r\n </div>\r\n </div>\r\n <button class=\"btn btn-secondary btn-sm\" (click)=\"addListItem()\">\r\n <clr-icon shape=\"plus\"></clr-icon> {{ 'common.add-item-to-list' | translate }}\r\n </button>\r\n </div>\r\n</ng-template>\r\n", styles: [":host{flex:1}.list-container{border:1px solid var(--color-component-border-200);border-radius:3px;padding:12px}.list-item-row{font-size:13px;display:flex;align-items:center;margin:3px 0}.drag-placeholder{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-preview{font-size:13px;background-color:var(--color-component-bg-100);opacity:.8;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:.1}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .list-item-row:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"] }]
9907
+ }], ctorParameters: function () { return [{ type: ComponentRegistryService }, { type: i0.ComponentFactoryResolver }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }]; }, propDecorators: { def: [{
9908
+ type: Input
9909
+ }], readonly: [{
9910
+ type: Input
9911
+ }], control: [{
9912
+ type: Input
9913
+ }], singleViewContainer: [{
9914
+ type: ViewChild,
9915
+ args: ['single', { read: ViewContainerRef }]
9916
+ }], listItemContainers: [{
9917
+ type: ViewChildren,
9918
+ args: ['listItem', { read: ViewContainerRef }]
9919
+ }] } });
9920
+
9921
+ /**
9922
+ * Formats a string into sentence case (first letter of first word uppercase).
9923
+ */
9924
+ class SentenceCasePipe {
9925
+ transform(value) {
9926
+ if (typeof value === 'string') {
9927
+ let lower;
9928
+ if (isCamelCase(value)) {
9929
+ lower = value.replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase();
9930
+ }
9931
+ else {
9932
+ lower = value.toLowerCase();
9933
+ }
9934
+ return lower.charAt(0).toUpperCase() + lower.slice(1);
9935
+ }
9936
+ return value;
9937
+ }
9938
+ }
9939
+ SentenceCasePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SentenceCasePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
9940
+ SentenceCasePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SentenceCasePipe, name: "sentenceCase" });
9941
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SentenceCasePipe, decorators: [{
9942
+ type: Pipe,
9943
+ args: [{ name: 'sentenceCase' }]
9944
+ }] });
9945
+ function isCamelCase(value) {
9946
+ return /^[a-zA-Z]+[A-Z][a-zA-Z]+$/.test(value);
9947
+ }
9948
+
9949
+ /**
9950
+ * A form input which renders a card with the internal form fields of the given ConfigurableOperation.
9951
+ */
9952
+ class ConfigurableInputComponent {
9953
+ constructor() {
9954
+ this.readonly = false;
9955
+ this.removable = true;
9956
+ this.position = 0;
9957
+ this.remove = new EventEmitter();
9958
+ this.argValues = {};
9959
+ this.form = new FormGroup({});
9960
+ this.positionChangeSubject = new BehaviorSubject(0);
9961
+ }
9962
+ interpolateDescription() {
9963
+ if (this.operationDefinition) {
9964
+ return interpolateDescription(this.operationDefinition, this.form.value);
9965
+ }
9966
+ else {
9967
+ return '';
9968
+ }
9969
+ }
9970
+ ngOnInit() {
9971
+ this.positionChange$ = this.positionChangeSubject.asObservable();
9972
+ }
9973
+ ngOnChanges(changes) {
9974
+ if ('operation' in changes || 'operationDefinition' in changes) {
9975
+ this.createForm();
9976
+ }
9977
+ if ('position' in changes) {
9978
+ this.positionChangeSubject.next(this.position);
9979
+ }
9980
+ }
9981
+ ngOnDestroy() {
9982
+ if (this.subscription) {
9983
+ this.subscription.unsubscribe();
9984
+ }
9985
+ }
9986
+ registerOnChange(fn) {
9987
+ this.onChange = fn;
9988
+ }
9989
+ registerOnTouched(fn) {
9990
+ this.onTouch = fn;
9991
+ }
9992
+ setDisabledState(isDisabled) {
9993
+ if (isDisabled) {
9994
+ this.form.disable();
9995
+ }
9996
+ else {
9997
+ this.form.enable();
9998
+ }
9999
+ }
10000
+ writeValue(value) {
10001
+ if (value) {
10002
+ this.form.patchValue(value);
10003
+ }
10004
+ }
10005
+ trackByName(index, arg) {
10006
+ return arg.name;
10007
+ }
10008
+ getArgDef(arg) {
10009
+ var _a;
10010
+ return (_a = this.operationDefinition) === null || _a === void 0 ? void 0 : _a.args.find(a => a.name === arg.name);
10011
+ }
10012
+ createForm() {
10013
+ var _a, _b;
10014
+ if (!this.operation) {
10015
+ return;
10016
+ }
10017
+ if (this.subscription) {
10018
+ this.subscription.unsubscribe();
10019
+ }
10020
+ this.form = new FormGroup({});
10021
+ this.form.__id = Math.random().toString(36).substr(10);
10022
+ if (this.operation.args) {
10023
+ for (const arg of ((_a = this.operationDefinition) === null || _a === void 0 ? void 0 : _a.args) || []) {
10024
+ let value = (_b = this.operation.args.find(a => a.name === arg.name)) === null || _b === void 0 ? void 0 : _b.value;
10025
+ if (value === undefined) {
10026
+ value = getDefaultConfigArgValue(arg);
10027
+ }
10028
+ const validators = arg.list ? undefined : arg.required ? Validators.required : undefined;
10029
+ this.form.addControl(arg.name, new FormControl(value, validators));
10030
+ }
10031
+ }
10032
+ this.subscription = this.form.valueChanges.subscribe(value => {
10033
+ if (this.onChange) {
10034
+ this.onChange({
10035
+ code: this.operation && this.operation.code,
10036
+ args: value,
10037
+ });
10038
+ }
10039
+ if (this.onTouch) {
10040
+ this.onTouch();
10041
+ }
10042
+ });
10043
+ }
10044
+ validate(c) {
10045
+ if (this.form.invalid) {
10046
+ return {
10047
+ required: true,
10048
+ };
10049
+ }
10050
+ return null;
10051
+ }
10052
+ }
10053
+ ConfigurableInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ConfigurableInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10054
+ ConfigurableInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ConfigurableInputComponent, selector: "vdr-configurable-input", inputs: { operation: "operation", operationDefinition: "operationDefinition", readonly: "readonly", removable: "removable", position: "position" }, outputs: { remove: "remove" }, providers: [
10055
+ {
10056
+ provide: NG_VALUE_ACCESSOR,
10057
+ useExisting: ConfigurableInputComponent,
10058
+ multi: true,
10059
+ },
10060
+ {
10061
+ provide: NG_VALIDATORS,
10062
+ useExisting: forwardRef(() => ConfigurableInputComponent),
10063
+ multi: true,
10064
+ },
10065
+ ], usesOnChanges: true, ngImport: i0, template: "<div class=\"card\" *ngIf=\"operation\">\r\n <div class=\"card-block\">{{ interpolateDescription() }}</div>\r\n <div class=\"card-block\" *ngIf=\"operation.args?.length\">\r\n <form [formGroup]=\"form\" *ngIf=\"operation\" class=\"operation-inputs\">\r\n <div *ngFor=\"let arg of operation.args; trackBy: trackByName\" class=\"arg-row\">\r\n <ng-container *ngIf=\"form.get(arg.name) && getArgDef(arg) as argDef\">\r\n <label class=\"clr-control-label\">{{ argDef.label || (arg.name | sentenceCase) }}</label>\r\n <vdr-help-tooltip\r\n class=\"mr3\"\r\n *ngIf=\"argDef.description\"\r\n [content]=\"argDef.description\"\r\n ></vdr-help-tooltip>\r\n <vdr-dynamic-form-input\r\n [def]=\"getArgDef(arg)\"\r\n [readonly]=\"readonly\"\r\n [control]=\"form.get(arg.name)\"\r\n [formControlName]=\"arg.name\"\r\n ></vdr-dynamic-form-input>\r\n </ng-container>\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"card-footer\" *ngIf=\"!readonly && removable\">\r\n <button class=\"btn btn-sm btn-link btn-warning\" (click)=\"remove.emit(operation)\">\r\n <clr-icon shape=\"times\"></clr-icon>\r\n {{ 'common.remove' | translate }}\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;margin-bottom:12px}:host>.card{margin-top:6px}.operation-inputs{padding-top:0}.operation-inputs .arg-row:not(:last-child){margin-bottom:12px}.operation-inputs .arg-row{display:flex;flex-wrap:wrap;align-items:center}.operation-inputs .arg-row label{margin-right:6px}.operation-inputs .hidden{display:none}.operation-inputs label{min-width:130px;display:inline-block}\n"], components: [{ type: HelpTooltipComponent, selector: "vdr-help-tooltip", inputs: ["content", "position"] }, { type: DynamicFormInputComponent, selector: "vdr-dynamic-form-input", inputs: ["def", "readonly", "control"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$3.ClrDatagridItemsTrackBy, selector: "[ngForTrackBy]", inputs: ["ngForTrackBy"] }, { type: i1$3.ClrLabel, selector: "label", inputs: ["for"] }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }], pipes: { "sentenceCase": SentenceCasePipe, "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
10066
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ConfigurableInputComponent, decorators: [{
10067
+ type: Component,
10068
+ args: [{ selector: 'vdr-configurable-input', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
10069
+ {
10070
+ provide: NG_VALUE_ACCESSOR,
10071
+ useExisting: ConfigurableInputComponent,
10072
+ multi: true,
10073
+ },
10074
+ {
10075
+ provide: NG_VALIDATORS,
10076
+ useExisting: forwardRef(() => ConfigurableInputComponent),
10077
+ multi: true,
10078
+ },
10079
+ ], template: "<div class=\"card\" *ngIf=\"operation\">\r\n <div class=\"card-block\">{{ interpolateDescription() }}</div>\r\n <div class=\"card-block\" *ngIf=\"operation.args?.length\">\r\n <form [formGroup]=\"form\" *ngIf=\"operation\" class=\"operation-inputs\">\r\n <div *ngFor=\"let arg of operation.args; trackBy: trackByName\" class=\"arg-row\">\r\n <ng-container *ngIf=\"form.get(arg.name) && getArgDef(arg) as argDef\">\r\n <label class=\"clr-control-label\">{{ argDef.label || (arg.name | sentenceCase) }}</label>\r\n <vdr-help-tooltip\r\n class=\"mr3\"\r\n *ngIf=\"argDef.description\"\r\n [content]=\"argDef.description\"\r\n ></vdr-help-tooltip>\r\n <vdr-dynamic-form-input\r\n [def]=\"getArgDef(arg)\"\r\n [readonly]=\"readonly\"\r\n [control]=\"form.get(arg.name)\"\r\n [formControlName]=\"arg.name\"\r\n ></vdr-dynamic-form-input>\r\n </ng-container>\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"card-footer\" *ngIf=\"!readonly && removable\">\r\n <button class=\"btn btn-sm btn-link btn-warning\" (click)=\"remove.emit(operation)\">\r\n <clr-icon shape=\"times\"></clr-icon>\r\n {{ 'common.remove' | translate }}\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;margin-bottom:12px}:host>.card{margin-top:6px}.operation-inputs{padding-top:0}.operation-inputs .arg-row:not(:last-child){margin-bottom:12px}.operation-inputs .arg-row{display:flex;flex-wrap:wrap;align-items:center}.operation-inputs .arg-row label{margin-right:6px}.operation-inputs .hidden{display:none}.operation-inputs label{min-width:130px;display:inline-block}\n"] }]
10080
+ }], propDecorators: { operation: [{
10081
+ type: Input
10082
+ }], operationDefinition: [{
10083
+ type: Input
10084
+ }], readonly: [{
10085
+ type: Input
10086
+ }], removable: [{
10087
+ type: Input
10088
+ }], position: [{
10089
+ type: Input
10090
+ }], remove: [{
10091
+ type: Output
10092
+ }] } });
10093
+
10094
+ /**
10095
+ * @description
10096
+ * A special input used to display the "Combination mode" AND/OR toggle.
10097
+ *
10098
+ * @docsCategory custom-input-components
10099
+ * @docsPage default-inputs
10100
+ */
10101
+ class CombinationModeFormInputComponent {
10102
+ constructor(configurableInputComponent) {
10103
+ this.configurableInputComponent = configurableInputComponent;
10104
+ }
10105
+ ngOnInit() {
10106
+ const selectable$ = this.configurableInputComponent
10107
+ ? this.configurableInputComponent.positionChange$.pipe(map(position => 0 < position))
10108
+ : of(true);
10109
+ this.selectable$ = selectable$.pipe(tap(selectable => {
10110
+ if (!selectable) {
10111
+ this.formControl.setValue(true, { emitEvent: false });
10112
+ }
10113
+ }));
10114
+ }
10115
+ setCombinationModeAnd() {
10116
+ this.formControl.setValue(true);
10117
+ }
10118
+ setCombinationModeOr() {
10119
+ this.formControl.setValue(false);
10120
+ }
10121
+ }
10122
+ CombinationModeFormInputComponent.id = 'combination-mode-form-input';
10123
+ CombinationModeFormInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: CombinationModeFormInputComponent, deps: [{ token: ConfigurableInputComponent, optional: true }], target: i0.ɵɵFactoryTarget.Component });
10124
+ CombinationModeFormInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: CombinationModeFormInputComponent, selector: "vdr-combination-mode-form-input", ngImport: i0, template: "<ng-container *ngIf=\"selectable$ | async; else default\">\r\n <div class=\"btn-group btn-outline-primary btn-sm mode-select\">\r\n <button\r\n class=\"btn\"\r\n (click)=\"setCombinationModeAnd()\"\r\n [class.btn-primary]=\"formControl.value === true\"\r\n >\r\n {{ 'common.boolean-and' | translate }}\r\n </button>\r\n <button\r\n class=\"btn\"\r\n (click)=\"setCombinationModeOr()\"\r\n [class.btn-primary]=\"formControl.value === false\"\r\n >\r\n {{ 'common.boolean-or' | translate }}\r\n </button>\r\n </div>\r\n</ng-container>\r\n<ng-template #default>\r\n <small>{{ 'common.not-applicable' | translate }}</small>\r\n</ng-template>\r\n", styles: [".mode-select{text-transform:uppercase}\n"], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i3.AsyncPipe, "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
10125
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: CombinationModeFormInputComponent, decorators: [{
10126
+ type: Component,
10127
+ args: [{ selector: 'vdr-combination-mode-form-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"selectable$ | async; else default\">\r\n <div class=\"btn-group btn-outline-primary btn-sm mode-select\">\r\n <button\r\n class=\"btn\"\r\n (click)=\"setCombinationModeAnd()\"\r\n [class.btn-primary]=\"formControl.value === true\"\r\n >\r\n {{ 'common.boolean-and' | translate }}\r\n </button>\r\n <button\r\n class=\"btn\"\r\n (click)=\"setCombinationModeOr()\"\r\n [class.btn-primary]=\"formControl.value === false\"\r\n >\r\n {{ 'common.boolean-or' | translate }}\r\n </button>\r\n </div>\r\n</ng-container>\r\n<ng-template #default>\r\n <small>{{ 'common.not-applicable' | translate }}</small>\r\n</ng-template>\r\n", styles: [".mode-select{text-transform:uppercase}\n"] }]
10128
+ }], ctorParameters: function () {
10129
+ return [{ type: ConfigurableInputComponent, decorators: [{
10130
+ type: Optional
10131
+ }] }];
10132
+ } });
10133
+
10134
+ /**
10135
+ * A wrapper around an <input> element which adds a prefix and/or a suffix element.
10136
+ */
10137
+ class AffixedInputComponent {
10138
+ }
10139
+ AffixedInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AffixedInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10140
+ AffixedInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: AffixedInputComponent, selector: "vdr-affixed-input", inputs: { prefix: "prefix", suffix: "suffix" }, ngImport: i0, template: "<div [class.has-prefix]=\"!!prefix\" [class.has-suffix]=\"!!suffix\">\r\n <ng-content></ng-content>\r\n</div>\r\n<div class=\"affix prefix\" *ngIf=\"prefix\">{{ prefix }}</div>\r\n<div class=\"affix suffix\" *ngIf=\"suffix\">{{ suffix }}</div>\r\n", styles: [":host{display:inline-flex}.affix{color:var(--color-grey-800);display:flex;align-items:center;background-color:var(--color-grey-200);border:1px solid var(--color-component-border-300);top:1px;padding:3px;line-height:.58333rem;transition:border .2s}::ng-deep .has-prefix input{border-top-left-radius:0!important;border-bottom-left-radius:0!important}.prefix{order:-1;border-radius:3px 0 0 3px;border-right:none}::ng-deep .has-suffix input{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.suffix{border-radius:0 3px 3px 0;border-left:none}\n"], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10141
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AffixedInputComponent, decorators: [{
10142
+ type: Component,
10143
+ args: [{ selector: 'vdr-affixed-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class.has-prefix]=\"!!prefix\" [class.has-suffix]=\"!!suffix\">\r\n <ng-content></ng-content>\r\n</div>\r\n<div class=\"affix prefix\" *ngIf=\"prefix\">{{ prefix }}</div>\r\n<div class=\"affix suffix\" *ngIf=\"suffix\">{{ suffix }}</div>\r\n", styles: [":host{display:inline-flex}.affix{color:var(--color-grey-800);display:flex;align-items:center;background-color:var(--color-grey-200);border:1px solid var(--color-component-border-300);top:1px;padding:3px;line-height:.58333rem;transition:border .2s}::ng-deep .has-prefix input{border-top-left-radius:0!important;border-bottom-left-radius:0!important}.prefix{order:-1;border-radius:3px 0 0 3px;border-right:none}::ng-deep .has-suffix input{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.suffix{border-radius:0 3px 3px 0;border-left:none}\n"] }]
10144
+ }], propDecorators: { prefix: [{
10145
+ type: Input
10146
+ }], suffix: [{
10147
+ type: Input
10148
+ }] } });
10149
+
10150
+ /**
10151
+ * @description
10152
+ * A form input control which displays currency in decimal format, whilst working
10153
+ * with the integer cent value in the background.
10154
+ *
10155
+ * @example
10156
+ * ```HTML
10157
+ * <vdr-currency-input
10158
+ * [(ngModel)]="entityPrice"
10159
+ * [currencyCode]="currencyCode"
10160
+ * ></vdr-currency-input>
10161
+ * ```
10162
+ *
10163
+ * @docsCategory components
10164
+ */
10165
+ class CurrencyInputComponent {
10166
+ constructor(dataService, changeDetectorRef) {
10167
+ this.dataService = dataService;
10168
+ this.changeDetectorRef = changeDetectorRef;
10169
+ this.disabled = false;
10170
+ this.readonly = false;
10171
+ this.currencyCode = '';
10172
+ this.valueChange = new EventEmitter();
10173
+ this.hasFractionPart = true;
10174
+ this.currencyCode$ = new BehaviorSubject('');
10175
+ }
10176
+ ngOnInit() {
10177
+ const languageCode$ = this.dataService.client.uiState().mapStream(data => data.uiState.language);
10178
+ const shouldPrefix$ = combineLatest(languageCode$, this.currencyCode$).pipe(map(([languageCode, currencyCode]) => {
10179
+ var _a, _b;
10180
+ if (!currencyCode) {
9573
10181
  return '';
9574
10182
  }
9575
10183
  const locale = languageCode.replace(/_/g, '-');
@@ -10452,245 +11060,77 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImpor
10452
11060
  */
10453
11061
  class PasswordFormInputComponent {
10454
11062
  }
10455
- PasswordFormInputComponent.id = 'password-form-input';
10456
- PasswordFormInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: PasswordFormInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10457
- PasswordFormInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: PasswordFormInputComponent, selector: "vdr-password-form-input", ngImport: i0, template: "<input\r\n type=\"password\"\r\n [readonly]=\"readonly\"\r\n [formControl]=\"formControl\"\r\n/>\r\n", styles: [""], directives: [{ type: FormFieldControlDirective, selector: "input, textarea, select" }, { type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10458
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: PasswordFormInputComponent, decorators: [{
10459
- type: Component,
10460
- args: [{ selector: 'vdr-password-form-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<input\r\n type=\"password\"\r\n [readonly]=\"readonly\"\r\n [formControl]=\"formControl\"\r\n/>\r\n", styles: [""] }]
10461
- }] });
10462
-
10463
- /**
10464
- * @description
10465
- * Given an Asset object (an object with `preview` and optionally `focalPoint` properties), this pipe
10466
- * returns a string with query parameters designed to work with the image resize capabilities of the
10467
- * AssetServerPlugin.
10468
- *
10469
- * @example
10470
- * ```HTML
10471
- * <img [src]="asset | assetPreview:'tiny'" />
10472
- * <img [src]="asset | assetPreview:150" />
10473
- * ```
10474
- *
10475
- * @docsCategory pipes
10476
- */
10477
- class AssetPreviewPipe {
10478
- transform(asset, preset = 'thumb') {
10479
- if (!asset) {
10480
- return '';
10481
- }
10482
- if (asset.preview == null || typeof asset.preview !== 'string') {
10483
- throw new Error(`Expected an Asset, got ${JSON.stringify(asset)}`);
10484
- }
10485
- const fp = asset.focalPoint ? `&fpx=${asset.focalPoint.x}&fpy=${asset.focalPoint.y}` : '';
10486
- if (Number.isNaN(Number(preset))) {
10487
- return `${asset.preview}?preset=${preset}${fp}`;
10488
- }
10489
- else {
10490
- return `${asset.preview}?w=${preset}&h=${preset}${fp}`;
10491
- }
10492
- }
10493
- }
10494
- AssetPreviewPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetPreviewPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
10495
- AssetPreviewPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetPreviewPipe, name: "assetPreview" });
10496
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetPreviewPipe, decorators: [{
10497
- type: Pipe,
10498
- args: [{
10499
- name: 'assetPreview',
10500
- }]
10501
- }] });
10502
-
10503
- /**
10504
- * @description
10505
- * A component for selecting product variants via an autocomplete-style select input.
10506
- *
10507
- * @example
10508
- * ```HTML
10509
- * <vdr-product-variant-selector
10510
- * (productSelected)="selectResult($event)"></vdr-product-selector>
10511
- * ```
10512
- *
10513
- * @docsCategory components
10514
- */
10515
- class ProductVariantSelectorComponent {
10516
- constructor(dataService) {
10517
- this.dataService = dataService;
10518
- this.searchInput$ = new Subject();
10519
- this.searchLoading = false;
10520
- this.productSelected = new EventEmitter();
10521
- }
10522
- ngOnInit() {
10523
- this.initSearchResults();
10524
- }
10525
- initSearchResults() {
10526
- const searchItems$ = this.searchInput$.pipe(debounceTime(200), distinctUntilChanged(), tap(() => (this.searchLoading = true)), switchMap(term => {
10527
- if (!term) {
10528
- return of([]);
10529
- }
10530
- return this.dataService.product
10531
- .productSelectorSearch(term, 10)
10532
- .mapSingle(result => result.search.items);
10533
- }), tap(() => (this.searchLoading = false)));
10534
- const clear$ = this.productSelected.pipe(mapTo([]));
10535
- this.searchResults$ = concat(of([]), merge(searchItems$, clear$));
10536
- }
10537
- selectResult(product) {
10538
- if (product) {
10539
- this.productSelected.emit(product);
10540
- this.ngSelect.clearModel();
10541
- }
10542
- }
10543
- }
10544
- ProductVariantSelectorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductVariantSelectorComponent, deps: [{ token: DataService }], target: i0.ɵɵFactoryTarget.Component });
10545
- ProductVariantSelectorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ProductVariantSelectorComponent, selector: "vdr-product-variant-selector", outputs: { productSelected: "productSelected" }, viewQueries: [{ propertyName: "ngSelect", first: true, predicate: ["autoComplete"], descendants: true, static: true }], ngImport: i0, template: "<ng-select\r\n #autoComplete\r\n [items]=\"searchResults$ | async\"\r\n [addTag]=\"false\"\r\n [multiple]=\"false\"\r\n [hideSelected]=\"true\"\r\n [loading]=\"searchLoading\"\r\n [typeahead]=\"searchInput$\"\r\n [appendTo]=\"'body'\"\r\n [placeholder]=\"'settings.search-by-product-name-or-sku' | translate\"\r\n (change)=\"selectResult($event)\"\r\n>\r\n <ng-template ng-option-tmp let-item=\"item\">\r\n <img [src]=\"item.productAsset | assetPreview: 32\">\r\n {{ item.productVariantName }}\r\n <small class=\"sku\">{{ item.sku }}</small>\r\n </ng-template>\r\n</ng-select>\r\n", styles: [":host{display:block}.sku{margin-left:12px;color:var(--color-grey-500)}\n"], components: [{ type: i2$1.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }], directives: [{ type: i2$1.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }], pipes: { "async": i3.AsyncPipe, "translate": i7.TranslatePipe, "assetPreview": AssetPreviewPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
10546
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductVariantSelectorComponent, decorators: [{
10547
- type: Component,
10548
- args: [{ selector: 'vdr-product-variant-selector', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-select\r\n #autoComplete\r\n [items]=\"searchResults$ | async\"\r\n [addTag]=\"false\"\r\n [multiple]=\"false\"\r\n [hideSelected]=\"true\"\r\n [loading]=\"searchLoading\"\r\n [typeahead]=\"searchInput$\"\r\n [appendTo]=\"'body'\"\r\n [placeholder]=\"'settings.search-by-product-name-or-sku' | translate\"\r\n (change)=\"selectResult($event)\"\r\n>\r\n <ng-template ng-option-tmp let-item=\"item\">\r\n <img [src]=\"item.productAsset | assetPreview: 32\">\r\n {{ item.productVariantName }}\r\n <small class=\"sku\">{{ item.sku }}</small>\r\n </ng-template>\r\n</ng-select>\r\n", styles: [":host{display:block}.sku{margin-left:12px;color:var(--color-grey-500)}\n"] }]
10549
- }], ctorParameters: function () { return [{ type: DataService }]; }, propDecorators: { productSelected: [{
10550
- type: Output
10551
- }], ngSelect: [{
10552
- type: ViewChild,
10553
- args: ['autoComplete', { static: true }]
10554
- }] } });
10555
-
10556
- /**
10557
- * @description
10558
- * Allows the selection of multiple ProductVariants via an autocomplete select input.
10559
- * Should be used with `ID` type **list** fields which represent ProductVariant IDs.
10560
- *
10561
- * @docsCategory custom-input-components
10562
- * @docsPage default-inputs
10563
- */
10564
- class ProductSelectorFormInputComponent {
10565
- constructor(dataService) {
10566
- this.dataService = dataService;
10567
- this.isListInput = true;
10568
- }
10569
- ngOnInit() {
10570
- this.formControl.setValidators([
10571
- control => {
10572
- if (!control.value || !control.value.length) {
10573
- return {
10574
- atLeastOne: { length: control.value.length },
10575
- };
10576
- }
10577
- return null;
10578
- },
10579
- ]);
10580
- this.selection$ = this.formControl.valueChanges.pipe(startWith(this.formControl.value), switchMap(value => {
10581
- if (Array.isArray(value) && 0 < value.length) {
10582
- return forkJoin(value.map(id => this.dataService.product
10583
- .getProductVariant(id)
10584
- .mapSingle(data => data.productVariant)));
10585
- }
10586
- return of([]);
10587
- }), map(variants => variants.filter(notNullOrUndefined)));
10588
- }
10589
- addProductVariant(product) {
10590
- const value = this.formControl.value;
10591
- this.formControl.setValue([...new Set([...value, product.productVariantId])]);
10592
- }
10593
- removeProductVariant(id) {
10594
- const value = this.formControl.value;
10595
- this.formControl.setValue(value.filter(_id => _id !== id));
10596
- }
10597
- }
10598
- ProductSelectorFormInputComponent.id = 'product-selector-form-input';
10599
- ProductSelectorFormInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductSelectorFormInputComponent, deps: [{ token: DataService }], target: i0.ɵɵFactoryTarget.Component });
10600
- ProductSelectorFormInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ProductSelectorFormInputComponent, selector: "vdr-product-selector-form-input", ngImport: i0, template: "<ul class=\"list-unstyled\">\r\n <li *ngFor=\"let variant of selection$ | async\" class=\"variant\">\r\n <div class=\"thumb\">\r\n <img [src]=\"variant.product.featuredAsset | assetPreview: 32\" />\r\n </div>\r\n <div class=\"detail\">\r\n <div>{{ variant.name }}</div>\r\n <div class=\"sku\">{{ variant.sku }}</div>\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <button\r\n class=\"btn btn-link btn-sm btn-warning\"\r\n (click)=\"removeProductVariant(variant.id)\"\r\n [title]=\"'common.remove-item-from-list' | translate\"\r\n >\r\n <clr-icon shape=\"times\"></clr-icon>\r\n </button>\r\n </li>\r\n</ul>\r\n<vdr-product-variant-selector (productSelected)=\"addProductVariant($event)\"></vdr-product-variant-selector>\r\n", styles: [".variant{margin-bottom:6px;display:flex;align-items:center;transition:background-color .2s}.variant:hover{background-color:var(--color-component-bg-200)}.thumb{margin-right:6px}.sku{color:var(--color-grey-400);font-size:smaller;line-height:1em}\n"], components: [{ type: ProductVariantSelectorComponent, selector: "vdr-product-variant-selector", outputs: ["productSelected"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }], pipes: { "async": i3.AsyncPipe, "assetPreview": AssetPreviewPipe, "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
10601
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductSelectorFormInputComponent, decorators: [{
11063
+ PasswordFormInputComponent.id = 'password-form-input';
11064
+ PasswordFormInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: PasswordFormInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11065
+ PasswordFormInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: PasswordFormInputComponent, selector: "vdr-password-form-input", ngImport: i0, template: "<input\r\n type=\"password\"\r\n [readonly]=\"readonly\"\r\n [formControl]=\"formControl\"\r\n/>\r\n", styles: [""], directives: [{ type: FormFieldControlDirective, selector: "input, textarea, select" }, { type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11066
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: PasswordFormInputComponent, decorators: [{
10602
11067
  type: Component,
10603
- args: [{ selector: 'vdr-product-selector-form-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ul class=\"list-unstyled\">\r\n <li *ngFor=\"let variant of selection$ | async\" class=\"variant\">\r\n <div class=\"thumb\">\r\n <img [src]=\"variant.product.featuredAsset | assetPreview: 32\" />\r\n </div>\r\n <div class=\"detail\">\r\n <div>{{ variant.name }}</div>\r\n <div class=\"sku\">{{ variant.sku }}</div>\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <button\r\n class=\"btn btn-link btn-sm btn-warning\"\r\n (click)=\"removeProductVariant(variant.id)\"\r\n [title]=\"'common.remove-item-from-list' | translate\"\r\n >\r\n <clr-icon shape=\"times\"></clr-icon>\r\n </button>\r\n </li>\r\n</ul>\r\n<vdr-product-variant-selector (productSelected)=\"addProductVariant($event)\"></vdr-product-variant-selector>\r\n", styles: [".variant{margin-bottom:6px;display:flex;align-items:center;transition:background-color .2s}.variant:hover{background-color:var(--color-component-bg-200)}.thumb{margin-right:6px}.sku{color:var(--color-grey-400);font-size:smaller;line-height:1em}\n"] }]
10604
- }], ctorParameters: function () { return [{ type: DataService }]; } });
11068
+ args: [{ selector: 'vdr-password-form-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<input\r\n type=\"password\"\r\n [readonly]=\"readonly\"\r\n [formControl]=\"formControl\"\r\n/>\r\n", styles: [""] }]
11069
+ }] });
10605
11070
 
10606
11071
  /**
10607
- * A component for selecting files to upload as new Assets.
11072
+ * @description
11073
+ * A helper class used to manage selection of list items. Supports multiple selection via
11074
+ * cmd/ctrl/shift key.
10608
11075
  */
10609
- class AssetFileInputComponent {
10610
- constructor(serverConfig) {
10611
- this.serverConfig = serverConfig;
10612
- /**
10613
- * CSS selector of the DOM element which will be masked by the file
10614
- * drop zone. Defaults to `body`.
10615
- */
10616
- this.dropZoneTarget = 'body';
10617
- this.uploading = false;
10618
- this.selectFiles = new EventEmitter();
10619
- this.dragging = false;
10620
- this.overDropZone = false;
10621
- this.dropZoneStyle = {
10622
- 'width.px': 0,
10623
- 'height.px': 0,
10624
- 'top.px': 0,
10625
- 'left.px': 0,
10626
- };
10627
- }
10628
- ngOnInit() {
10629
- this.accept = this.serverConfig.serverConfig.permittedAssetTypes.join(',');
10630
- this.fitDropZoneToTarget();
10631
- }
10632
- onDragEnter() {
10633
- this.dragging = true;
10634
- this.fitDropZoneToTarget();
10635
- }
10636
- // DragEvent is not supported in Safari, see https://github.com/vendure-ecommerce/vendure/pull/284
10637
- onDragLeave(event) {
10638
- if (!event.clientX && !event.clientY) {
10639
- this.dragging = false;
11076
+ class SelectionManager {
11077
+ constructor(options) {
11078
+ this.options = options;
11079
+ this._selection = [];
11080
+ this.items = [];
11081
+ }
11082
+ get selection() {
11083
+ return this._selection;
11084
+ }
11085
+ setMultiSelect(isMultiSelect) {
11086
+ this.options.multiSelect = isMultiSelect;
11087
+ }
11088
+ setCurrentItems(items) {
11089
+ this.items = items;
11090
+ }
11091
+ toggleSelection(item, event) {
11092
+ const { multiSelect, itemsAreEqual, additiveMode } = this.options;
11093
+ const index = this._selection.findIndex(a => itemsAreEqual(a, item));
11094
+ if (multiSelect && (event === null || event === void 0 ? void 0 : event.shiftKey) && 1 <= this._selection.length) {
11095
+ const lastSelection = this._selection[this._selection.length - 1];
11096
+ const lastSelectionIndex = this.items.findIndex(a => itemsAreEqual(a, lastSelection));
11097
+ const currentIndex = this.items.findIndex(a => itemsAreEqual(a, item));
11098
+ const start = currentIndex < lastSelectionIndex ? currentIndex : lastSelectionIndex;
11099
+ const end = currentIndex > lastSelectionIndex ? currentIndex + 1 : lastSelectionIndex;
11100
+ this._selection.push(...this.items.slice(start, end).filter(a => !this._selection.find(s => itemsAreEqual(a, s))));
10640
11101
  }
11102
+ else if (index === -1) {
11103
+ if (multiSelect && ((event === null || event === void 0 ? void 0 : event.ctrlKey) || (event === null || event === void 0 ? void 0 : event.shiftKey) || additiveMode)) {
11104
+ this._selection.push(item);
11105
+ }
11106
+ else {
11107
+ this._selection = [item];
11108
+ }
11109
+ }
11110
+ else {
11111
+ if (multiSelect && (event === null || event === void 0 ? void 0 : event.ctrlKey)) {
11112
+ this._selection.splice(index, 1);
11113
+ }
11114
+ else if (1 < this._selection.length && !additiveMode) {
11115
+ this._selection = [item];
11116
+ }
11117
+ else {
11118
+ this._selection.splice(index, 1);
11119
+ }
11120
+ }
11121
+ // Make the selection mutable
11122
+ this._selection = this._selection.map(x => (Object.assign({}, x)));
10641
11123
  }
10642
- /**
10643
- * Preventing this event is required to make dropping work.
10644
- * See https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API#Define_a_drop_zone
10645
- */
10646
- onDragOver(event) {
10647
- event.preventDefault();
10648
- }
10649
- // DragEvent is not supported in Safari, see https://github.com/vendure-ecommerce/vendure/pull/284
10650
- onDrop(event) {
10651
- event.preventDefault();
10652
- this.dragging = false;
10653
- this.overDropZone = false;
10654
- const files = Array.from(event.dataTransfer ? event.dataTransfer.items : [])
10655
- .map(i => i.getAsFile())
10656
- .filter(notNullOrUndefined);
10657
- this.selectFiles.emit(files);
11124
+ selectMultiple(items) {
11125
+ this._selection = items;
10658
11126
  }
10659
- select(event) {
10660
- const files = event.target.files;
10661
- if (files) {
10662
- this.selectFiles.emit(Array.from(files));
10663
- }
11127
+ isSelected(item) {
11128
+ return !!this._selection.find(a => this.options.itemsAreEqual(a, item));
10664
11129
  }
10665
- fitDropZoneToTarget() {
10666
- const target = document.querySelector(this.dropZoneTarget);
10667
- if (target) {
10668
- const rect = target.getBoundingClientRect();
10669
- this.dropZoneStyle['width.px'] = rect.width;
10670
- this.dropZoneStyle['height.px'] = rect.height;
10671
- this.dropZoneStyle['top.px'] = rect.top;
10672
- this.dropZoneStyle['left.px'] = rect.left;
10673
- }
11130
+ lastSelected() {
11131
+ return this._selection[this._selection.length - 1];
10674
11132
  }
10675
- }
10676
- AssetFileInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetFileInputComponent, deps: [{ token: ServerConfigService }], target: i0.ɵɵFactoryTarget.Component });
10677
- AssetFileInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: AssetFileInputComponent, selector: "vdr-asset-file-input", inputs: { dropZoneTarget: "dropZoneTarget", uploading: "uploading" }, outputs: { selectFiles: "selectFiles" }, host: { listeners: { "document:dragenter": "onDragEnter()", "document:dragleave": "onDragLeave($event)" } }, ngImport: i0, template: "<input type=\"file\" class=\"file-input\" #fileInput (change)=\"select($event)\" multiple [accept]=\"accept\" />\r\n<button class=\"btn btn-primary\" (click)=\"fileInput.click()\" [disabled]=\"uploading\">\r\n <ng-container *ngIf=\"uploading; else selectable\">\r\n <clr-spinner clrInline></clr-spinner>\r\n {{ 'asset.uploading' | translate }}\r\n </ng-container>\r\n <ng-template #selectable>\r\n <clr-icon shape=\"upload-cloud\"></clr-icon>\r\n {{ 'asset.upload-assets' | translate }}\r\n </ng-template>\r\n</button>\r\n<div\r\n class=\"drop-zone\"\r\n [ngStyle]=\"dropZoneStyle\"\r\n [class.visible]=\"dragging\"\r\n [class.dragging-over]=\"overDropZone\"\r\n (dragenter)=\"overDropZone = true\"\r\n (dragleave)=\"overDropZone = false\"\r\n (dragover)=\"onDragOver($event)\"\r\n (drop)=\"onDrop($event)\"\r\n #dropZone\r\n>\r\n <div class=\"drop-label\" (dragenter)=\"overDropZone = true\">\r\n <clr-icon shape=\"upload-cloud\" size=\"32\"></clr-icon>\r\n {{ 'catalog.drop-files-to-upload' | translate }}\r\n </div>\r\n</div>\r\n", styles: [".file-input{display:none}.drop-zone{position:fixed;background-color:var(--color-primary-500);border:3px dashed var(--color-component-border-300);opacity:0;visibility:hidden;z-index:1000;transition:opacity .2s,background-color .2s,visibility 0s .2s;display:flex;align-items:center;justify-content:center}.drop-zone.visible{opacity:.3;visibility:visible;transition:opacity .2s,background-color .2s,border .2s,visibility 0s}.drop-zone .drop-label{background-color:#fffc;border-radius:3px;padding:24px;font-size:32px;pointer-events:none;opacity:.5;transition:opacity .2s}.drop-zone.dragging-over{border-color:#fff;background-color:var(--color-primary-500);opacity:.7;transition:background-color .2s,border .2s}.drop-zone.dragging-over .drop-label{opacity:1}\n"], components: [{ type: i1$3.ClrSpinner, selector: "clr-spinner", inputs: ["clrInline", "clrInverse", "clrSmall", "clrMedium"] }], directives: [{ type: FormFieldControlDirective, selector: "input, textarea, select" }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], pipes: { "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
10678
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetFileInputComponent, decorators: [{
10679
- type: Component,
10680
- args: [{ selector: 'vdr-asset-file-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<input type=\"file\" class=\"file-input\" #fileInput (change)=\"select($event)\" multiple [accept]=\"accept\" />\r\n<button class=\"btn btn-primary\" (click)=\"fileInput.click()\" [disabled]=\"uploading\">\r\n <ng-container *ngIf=\"uploading; else selectable\">\r\n <clr-spinner clrInline></clr-spinner>\r\n {{ 'asset.uploading' | translate }}\r\n </ng-container>\r\n <ng-template #selectable>\r\n <clr-icon shape=\"upload-cloud\"></clr-icon>\r\n {{ 'asset.upload-assets' | translate }}\r\n </ng-template>\r\n</button>\r\n<div\r\n class=\"drop-zone\"\r\n [ngStyle]=\"dropZoneStyle\"\r\n [class.visible]=\"dragging\"\r\n [class.dragging-over]=\"overDropZone\"\r\n (dragenter)=\"overDropZone = true\"\r\n (dragleave)=\"overDropZone = false\"\r\n (dragover)=\"onDragOver($event)\"\r\n (drop)=\"onDrop($event)\"\r\n #dropZone\r\n>\r\n <div class=\"drop-label\" (dragenter)=\"overDropZone = true\">\r\n <clr-icon shape=\"upload-cloud\" size=\"32\"></clr-icon>\r\n {{ 'catalog.drop-files-to-upload' | translate }}\r\n </div>\r\n</div>\r\n", styles: [".file-input{display:none}.drop-zone{position:fixed;background-color:var(--color-primary-500);border:3px dashed var(--color-component-border-300);opacity:0;visibility:hidden;z-index:1000;transition:opacity .2s,background-color .2s,visibility 0s .2s;display:flex;align-items:center;justify-content:center}.drop-zone.visible{opacity:.3;visibility:visible;transition:opacity .2s,background-color .2s,border .2s,visibility 0s}.drop-zone .drop-label{background-color:#fffc;border-radius:3px;padding:24px;font-size:32px;pointer-events:none;opacity:.5;transition:opacity .2s}.drop-zone.dragging-over{border-color:#fff;background-color:var(--color-primary-500);opacity:.7;transition:background-color .2s,border .2s}.drop-zone.dragging-over .drop-label{opacity:1}\n"] }]
10681
- }], ctorParameters: function () { return [{ type: ServerConfigService }]; }, propDecorators: { dropZoneTarget: [{
10682
- type: Input
10683
- }], uploading: [{
10684
- type: Input
10685
- }], selectFiles: [{
10686
- type: Output
10687
- }], onDragEnter: [{
10688
- type: HostListener,
10689
- args: ['document:dragenter']
10690
- }], onDragLeave: [{
10691
- type: HostListener,
10692
- args: ['document:dragleave', ['$event']]
10693
- }] } });
11133
+ }
10694
11134
 
10695
11135
  /**
10696
11136
  * A custom SelectionModel for the NgSelect component which only allows a single
@@ -10743,20 +11183,28 @@ function SingleSearchSelectionModelFactory() {
10743
11183
  return new SingleSearchSelectionModel();
10744
11184
  }
10745
11185
 
10746
- class AssetSearchInputComponent {
11186
+ class ProductSearchInputComponent {
10747
11187
  constructor() {
10748
11188
  this.searchTermChange = new EventEmitter();
10749
- this.tagsChange = new EventEmitter();
11189
+ this.facetValueChange = new EventEmitter();
10750
11190
  this.lastTerm = '';
10751
- this.lastTagIds = [];
10752
- this.filterTagResults = (term, item) => {
10753
- if (!this.isTag(item)) {
11191
+ this.lastFacetValueIds = [];
11192
+ this.filterFacetResults = (term, item) => {
11193
+ if (!this.isFacetValueItem(item)) {
10754
11194
  return false;
10755
11195
  }
10756
- return item.value.toLowerCase().startsWith(term.toLowerCase());
11196
+ const cix = term.indexOf(':');
11197
+ const facetName = cix > -1 ? term.toLowerCase().slice(0, cix) : null;
11198
+ const facetVal = cix > -1 ? term.toLowerCase().slice(cix + 1) : term.toLowerCase();
11199
+ if (facetName) {
11200
+ return (item.facetValue.facet.name.toLowerCase().includes(facetName) &&
11201
+ item.facetValue.name.toLocaleLowerCase().includes(facetVal));
11202
+ }
11203
+ return (item.facetValue.name.toLowerCase().includes(term.toLowerCase()) ||
11204
+ item.facetValue.facet.name.toLowerCase().includes(term.toLowerCase()));
10757
11205
  };
10758
- this.isTag = (input) => {
10759
- return typeof input === 'object' && !!input && input.hasOwnProperty('value');
11206
+ this.isFacetValueItem = (input) => {
11207
+ return typeof input === 'object' && !!input && input.hasOwnProperty('facetValue');
10760
11208
  };
10761
11209
  }
10762
11210
  setSearchTerm(term) {
@@ -10764,28 +11212,28 @@ class AssetSearchInputComponent {
10764
11212
  this.selectComponent.select({ label: term, value: { label: term } });
10765
11213
  }
10766
11214
  else {
10767
- const currentTerm = this.selectComponent.selectedItems.find(i => !this.isTag(i.value));
11215
+ const currentTerm = this.selectComponent.selectedItems.find(i => !this.isFacetValueItem(i.value));
10768
11216
  if (currentTerm) {
10769
11217
  this.selectComponent.unselect(currentTerm);
10770
11218
  }
10771
11219
  }
10772
11220
  }
10773
- setTags(tags) {
11221
+ setFacetValues(ids) {
10774
11222
  const items = this.selectComponent.items;
10775
11223
  this.selectComponent.selectedItems.forEach(item => {
10776
- if (this.isTag(item.value) && !tags.map(t => t.id).includes(item.id)) {
11224
+ if (this.isFacetValueItem(item.value) && !ids.includes(item.value.facetValue.id)) {
10777
11225
  this.selectComponent.unselect(item);
10778
11226
  }
10779
11227
  });
10780
- tags.map(tag => {
10781
- return items === null || items === void 0 ? void 0 : items.find(item => this.isTag(item) && item.id === tag.id);
11228
+ ids.map(id => {
11229
+ return items === null || items === void 0 ? void 0 : items.find(item => this.isFacetValueItem(item) && item.facetValue.id === id);
10782
11230
  })
10783
11231
  .filter(notNullOrUndefined)
10784
11232
  .forEach(item => {
10785
11233
  const isSelected = this.selectComponent.selectedItems.find(i => {
10786
11234
  const val = i.value;
10787
- if (this.isTag(val)) {
10788
- return val.id === item.id;
11235
+ if (this.isFacetValueItem(val)) {
11236
+ return val.facetValue.id === item.facetValue.id;
10789
11237
  }
10790
11238
  return false;
10791
11239
  });
@@ -10798,540 +11246,732 @@ class AssetSearchInputComponent {
10798
11246
  if (!Array.isArray(selectedItems)) {
10799
11247
  selectedItems = [selectedItems];
10800
11248
  }
10801
- const searchTermItems = selectedItems.filter(item => !this.isTag(item));
10802
- if (1 < searchTermItems.length) {
10803
- for (let i = 0; i < searchTermItems.length - 1; i++) {
10804
- // this.selectComponent.unselect(searchTermItems[i] as any);
10805
- }
10806
- }
10807
- const searchTermItem = searchTermItems[searchTermItems.length - 1];
11249
+ const searchTermItem = selectedItems.find(item => !this.isFacetValueItem(item));
10808
11250
  const searchTerm = searchTermItem ? searchTermItem.label : '';
10809
- const tags = selectedItems.filter(this.isTag);
11251
+ const facetValueIds = selectedItems.filter(this.isFacetValueItem).map(i => i.facetValue.id);
10810
11252
  if (searchTerm !== this.lastTerm) {
10811
11253
  this.searchTermChange.emit(searchTerm);
10812
11254
  this.lastTerm = searchTerm;
10813
11255
  }
10814
- if (this.lastTagIds.join(',') !== tags.map(t => t.id).join(',')) {
10815
- this.tagsChange.emit(tags);
10816
- this.lastTagIds = tags.map(t => t.id);
11256
+ if (this.lastFacetValueIds.join(',') !== facetValueIds.join(',')) {
11257
+ this.facetValueChange.emit(facetValueIds);
11258
+ this.lastFacetValueIds = facetValueIds;
10817
11259
  }
10818
11260
  }
10819
- isSearchHeaderSelected() {
10820
- return this.selectComponent.itemsList.markedIndex === -1;
10821
- }
10822
11261
  addTagFn(item) {
10823
11262
  return { label: item };
10824
11263
  }
11264
+ isSearchHeaderSelected() {
11265
+ return this.selectComponent.itemsList.markedIndex === -1;
11266
+ }
10825
11267
  }
10826
- AssetSearchInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetSearchInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10827
- AssetSearchInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: AssetSearchInputComponent, selector: "vdr-asset-search-input", inputs: { tags: "tags" }, outputs: { searchTermChange: "searchTermChange", tagsChange: "tagsChange" }, providers: [{ provide: SELECTION_MODEL_FACTORY, useValue: SingleSearchSelectionModelFactory }], viewQueries: [{ propertyName: "selectComponent", first: true, predicate: ["selectComponent"], descendants: true, static: true }], ngImport: i0, template: "<ng-select\r\n [addTag]=\"addTagFn\"\r\n [placeholder]=\"'catalog.search-asset-name-or-tag' | translate\"\r\n [items]=\"tags\"\r\n [searchFn]=\"filterTagResults\"\r\n [hideSelected]=\"true\"\r\n [multiple]=\"true\"\r\n [markFirst]=\"false\"\r\n (change)=\"onSelectChange($event)\"\r\n #selectComponent\r\n>\r\n <ng-template ng-header-tmp>\r\n <div\r\n class=\"search-header\"\r\n *ngIf=\"selectComponent.searchTerm\"\r\n [class.selected]=\"isSearchHeaderSelected()\"\r\n (click)=\"selectComponent.selectTag()\"\r\n >\r\n {{ 'catalog.search-for-term' | translate }}: {{ selectComponent.searchTerm }}\r\n </div>\r\n </ng-template>\r\n <ng-template ng-label-tmp let-item=\"item\" let-clear=\"clear\">\r\n <ng-container *ngIf=\"item.value\">\r\n <vdr-chip [colorFrom]=\"item.value\" icon=\"close\" (iconClick)=\"clear(item)\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ item.value }}</vdr-chip>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.value\">\r\n <vdr-chip [icon]=\"'times'\" (iconClick)=\"clear(item)\">\"{{ item.label || item }}\"</vdr-chip>\r\n </ng-container>\r\n </ng-template>\r\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\r\n <ng-container *ngIf=\"item.value\">\r\n <vdr-chip [colorFrom]=\"item.value\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ item.value }}</vdr-chip>\r\n </ng-container>\r\n </ng-template>\r\n</ng-select>\r\n", styles: [":host{display:block;width:100%}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background:none;margin:0}:host ::ng-deep .ng-dropdown-panel-items div.ng-option:last-child{display:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border:none;padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-left:8px}ng-select{width:100%;min-width:300px;margin-right:12px}.search-header{padding:8px 10px;border-bottom:1px solid var(--color-component-border-100);cursor:pointer}.search-header.selected,.search-header:hover{background-color:var(--color-component-bg-200)}\n"], components: [{ type: i2$1.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { type: ChipComponent, selector: "vdr-chip", inputs: ["icon", "invert", "colorFrom", "colorType"], outputs: ["iconClick"] }], directives: [{ type: i2$1.NgHeaderTemplateDirective, selector: "[ng-header-tmp]" }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2$1.NgLabelTemplateDirective, selector: "[ng-label-tmp]" }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i2$1.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }], pipes: { "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
10828
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetSearchInputComponent, decorators: [{
11268
+ ProductSearchInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductSearchInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11269
+ ProductSearchInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ProductSearchInputComponent, selector: "vdr-product-search-input", inputs: { facetValueResults: "facetValueResults" }, outputs: { searchTermChange: "searchTermChange", facetValueChange: "facetValueChange" }, providers: [{ provide: SELECTION_MODEL_FACTORY, useValue: SingleSearchSelectionModelFactory }], viewQueries: [{ propertyName: "selectComponent", first: true, predicate: ["selectComponent"], descendants: true, static: true }], ngImport: i0, template: "<ng-select\r\n [addTag]=\"addTagFn\"\r\n [placeholder]=\"'catalog.search-product-name-or-code' | translate\"\r\n [items]=\"facetValueResults\"\r\n [searchFn]=\"filterFacetResults\"\r\n [hideSelected]=\"true\"\r\n [multiple]=\"true\"\r\n [markFirst]=\"false\"\r\n (change)=\"onSelectChange($event)\"\r\n #selectComponent\r\n>\r\n <ng-template ng-header-tmp>\r\n <div\r\n class=\"search-header\"\r\n *ngIf=\"selectComponent.searchTerm\"\r\n [class.selected]=\"isSearchHeaderSelected()\"\r\n (click)=\"selectComponent.selectTag()\"\r\n >\r\n {{ 'catalog.search-for-term' | translate }}: {{ selectComponent.searchTerm }}\r\n </div>\r\n </ng-template>\r\n <ng-template ng-label-tmp let-item=\"item\" let-clear=\"clear\">\r\n <ng-container *ngIf=\"item.facetValue\">\r\n <vdr-facet-value-chip\r\n [facetValue]=\"item.facetValue\"\r\n [removable]=\"true\"\r\n (remove)=\"clear(item)\"\r\n ></vdr-facet-value-chip>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.facetValue\">\r\n <vdr-chip [icon]=\"'times'\" (iconClick)=\"clear(item)\">\"{{ item.label }}\"</vdr-chip>\r\n </ng-container>\r\n </ng-template>\r\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\r\n <ng-container *ngIf=\"item.facetValue\">\r\n <vdr-facet-value-chip [facetValue]=\"item.facetValue\" [removable]=\"false\"></vdr-facet-value-chip>\r\n </ng-container>\r\n </ng-template>\r\n</ng-select>\r\n", styles: [":host{margin-top:6px;display:block;width:100%}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background:none;margin:0}:host ::ng-deep .ng-dropdown-panel-items div.ng-option:last-child{display:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border:none;padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-left:8px}ng-select{width:100%;min-width:300px;margin-right:12px}.search-header{padding:8px 10px;border-bottom:1px solid var(--color-component-border-100);cursor:pointer}.search-header.selected,.search-header:hover{background-color:var(--color-component-bg-200)}\n"], components: [{ type: i2$1.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { type: FacetValueChipComponent, selector: "vdr-facet-value-chip", inputs: ["facetValue", "removable", "displayFacetName"], outputs: ["remove"] }, { type: ChipComponent, selector: "vdr-chip", inputs: ["icon", "invert", "colorFrom", "colorType"], outputs: ["iconClick"] }], directives: [{ type: i2$1.NgHeaderTemplateDirective, selector: "[ng-header-tmp]" }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2$1.NgLabelTemplateDirective, selector: "[ng-label-tmp]" }, { type: i2$1.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }], pipes: { "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11270
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductSearchInputComponent, decorators: [{
10829
11271
  type: Component,
10830
- args: [{ selector: 'vdr-asset-search-input', changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: SELECTION_MODEL_FACTORY, useValue: SingleSearchSelectionModelFactory }], template: "<ng-select\r\n [addTag]=\"addTagFn\"\r\n [placeholder]=\"'catalog.search-asset-name-or-tag' | translate\"\r\n [items]=\"tags\"\r\n [searchFn]=\"filterTagResults\"\r\n [hideSelected]=\"true\"\r\n [multiple]=\"true\"\r\n [markFirst]=\"false\"\r\n (change)=\"onSelectChange($event)\"\r\n #selectComponent\r\n>\r\n <ng-template ng-header-tmp>\r\n <div\r\n class=\"search-header\"\r\n *ngIf=\"selectComponent.searchTerm\"\r\n [class.selected]=\"isSearchHeaderSelected()\"\r\n (click)=\"selectComponent.selectTag()\"\r\n >\r\n {{ 'catalog.search-for-term' | translate }}: {{ selectComponent.searchTerm }}\r\n </div>\r\n </ng-template>\r\n <ng-template ng-label-tmp let-item=\"item\" let-clear=\"clear\">\r\n <ng-container *ngIf=\"item.value\">\r\n <vdr-chip [colorFrom]=\"item.value\" icon=\"close\" (iconClick)=\"clear(item)\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ item.value }}</vdr-chip>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.value\">\r\n <vdr-chip [icon]=\"'times'\" (iconClick)=\"clear(item)\">\"{{ item.label || item }}\"</vdr-chip>\r\n </ng-container>\r\n </ng-template>\r\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\r\n <ng-container *ngIf=\"item.value\">\r\n <vdr-chip [colorFrom]=\"item.value\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ item.value }}</vdr-chip>\r\n </ng-container>\r\n </ng-template>\r\n</ng-select>\r\n", styles: [":host{display:block;width:100%}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background:none;margin:0}:host ::ng-deep .ng-dropdown-panel-items div.ng-option:last-child{display:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border:none;padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-left:8px}ng-select{width:100%;min-width:300px;margin-right:12px}.search-header{padding:8px 10px;border-bottom:1px solid var(--color-component-border-100);cursor:pointer}.search-header.selected,.search-header:hover{background-color:var(--color-component-bg-200)}\n"] }]
10831
- }], propDecorators: { tags: [{
11272
+ args: [{ selector: 'vdr-product-search-input', changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: SELECTION_MODEL_FACTORY, useValue: SingleSearchSelectionModelFactory }], template: "<ng-select\r\n [addTag]=\"addTagFn\"\r\n [placeholder]=\"'catalog.search-product-name-or-code' | translate\"\r\n [items]=\"facetValueResults\"\r\n [searchFn]=\"filterFacetResults\"\r\n [hideSelected]=\"true\"\r\n [multiple]=\"true\"\r\n [markFirst]=\"false\"\r\n (change)=\"onSelectChange($event)\"\r\n #selectComponent\r\n>\r\n <ng-template ng-header-tmp>\r\n <div\r\n class=\"search-header\"\r\n *ngIf=\"selectComponent.searchTerm\"\r\n [class.selected]=\"isSearchHeaderSelected()\"\r\n (click)=\"selectComponent.selectTag()\"\r\n >\r\n {{ 'catalog.search-for-term' | translate }}: {{ selectComponent.searchTerm }}\r\n </div>\r\n </ng-template>\r\n <ng-template ng-label-tmp let-item=\"item\" let-clear=\"clear\">\r\n <ng-container *ngIf=\"item.facetValue\">\r\n <vdr-facet-value-chip\r\n [facetValue]=\"item.facetValue\"\r\n [removable]=\"true\"\r\n (remove)=\"clear(item)\"\r\n ></vdr-facet-value-chip>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.facetValue\">\r\n <vdr-chip [icon]=\"'times'\" (iconClick)=\"clear(item)\">\"{{ item.label }}\"</vdr-chip>\r\n </ng-container>\r\n </ng-template>\r\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\r\n <ng-container *ngIf=\"item.facetValue\">\r\n <vdr-facet-value-chip [facetValue]=\"item.facetValue\" [removable]=\"false\"></vdr-facet-value-chip>\r\n </ng-container>\r\n </ng-template>\r\n</ng-select>\r\n", styles: [":host{margin-top:6px;display:block;width:100%}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background:none;margin:0}:host ::ng-deep .ng-dropdown-panel-items div.ng-option:last-child{display:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border:none;padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-left:8px}ng-select{width:100%;min-width:300px;margin-right:12px}.search-header{padding:8px 10px;border-bottom:1px solid var(--color-component-border-100);cursor:pointer}.search-header.selected,.search-header:hover{background-color:var(--color-component-bg-200)}\n"] }]
11273
+ }], propDecorators: { facetValueResults: [{
10832
11274
  type: Input
10833
11275
  }], searchTermChange: [{
10834
11276
  type: Output
10835
- }], tagsChange: [{
11277
+ }], facetValueChange: [{
10836
11278
  type: Output
10837
11279
  }], selectComponent: [{
10838
11280
  type: ViewChild,
10839
11281
  args: ['selectComponent', { static: true }]
10840
11282
  }] } });
10841
11283
 
10842
- class ManageTagsDialogComponent {
10843
- constructor(dataService) {
10844
- this.dataService = dataService;
10845
- this.toDelete = [];
10846
- this.toUpdate = [];
10847
- }
10848
- ngOnInit() {
10849
- this.allTags$ = this.dataService.product.getTagList().mapStream(data => data.tags.items);
10850
- }
10851
- toggleDelete(id) {
10852
- const marked = this.markedAsDeleted(id);
10853
- if (marked) {
10854
- this.toDelete = this.toDelete.filter(_id => _id !== id);
10855
- }
10856
- else {
10857
- this.toDelete.push(id);
10858
- }
10859
- }
10860
- markedAsDeleted(id) {
10861
- return this.toDelete.includes(id);
10862
- }
10863
- updateTagValue(id, value) {
10864
- const exists = this.toUpdate.find(i => i.id === id);
10865
- if (exists) {
10866
- exists.value = value;
10867
- }
10868
- else {
10869
- this.toUpdate.push({ id, value });
10870
- }
10871
- }
10872
- saveChanges() {
10873
- const operations = [];
10874
- for (const id of this.toDelete) {
10875
- operations.push(this.dataService.product.deleteTag(id));
10876
- }
10877
- for (const item of this.toUpdate) {
10878
- if (!this.toDelete.includes(item.id)) {
10879
- operations.push(this.dataService.product.updateTag(item));
10880
- }
10881
- }
10882
- return forkJoin(operations).subscribe(() => this.resolveWith(true));
11284
+ /**
11285
+ * A simple, stateless toggle button for indicating selection.
11286
+ */
11287
+ class SelectToggleComponent {
11288
+ constructor() {
11289
+ this.size = 'large';
11290
+ this.selected = false;
11291
+ this.hiddenWhenOff = false;
11292
+ this.disabled = false;
11293
+ this.selectedChange = new EventEmitter();
10883
11294
  }
10884
11295
  }
10885
- ManageTagsDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ManageTagsDialogComponent, deps: [{ token: DataService }], target: i0.ɵɵFactoryTarget.Component });
10886
- ManageTagsDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ManageTagsDialogComponent, selector: "vdr-manage-tags-dialog", ngImport: i0, template: "<ng-template vdrDialogTitle>\r\n <span>{{ 'common.manage-tags' | translate }}</span>\r\n</ng-template>\r\n<p class=\"mt0 mb4\">{{ 'common.manage-tags-description' | translate }}</p>\r\n<ul class=\"tag-list\" *ngFor=\"let tag of allTags$ | async\">\r\n <li class=\"mb2 p1\" [class.to-delete]=\"markedAsDeleted(tag.id)\">\r\n <clr-icon shape=\"tag\" class=\"is-solid mr2\" [style.color]=\"tag.value | stringToColor\"></clr-icon>\r\n <input type=\"text\" (input)=\"updateTagValue(tag.id, $event.target.value)\" [value]=\"tag.value\" />\r\n <button class=\"icon-button\" (click)=\"toggleDelete(tag.id)\">\r\n <clr-icon shape=\"trash\" class=\"is-danger\" [class.is-solid]=\"markedAsDeleted(tag.id)\"></clr-icon>\r\n </button>\r\n </li>\r\n</ul>\r\n<ng-template vdrDialogButtons>\r\n <button type=\"submit\" (click)=\"resolveWith(false)\" class=\"btn btn-secondary\">\r\n {{ 'common.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"submit\"\r\n (click)=\"saveChanges()\"\r\n class=\"btn btn-primary\"\r\n [disabled]=\"!toUpdate.length && !toDelete.length\"\r\n >\r\n {{ 'common.update' | translate }}\r\n </button>\r\n</ng-template>\r\n", styles: [".tag-list{list-style-type:none}.tag-list li{display:flex;align-items:center}.tag-list li input{max-width:170px}.tag-list li.to-delete{opacity:.7;background-color:var(--color-component-bg-300)}.tag-list li.to-delete input{background-color:transparent!important}\n"], directives: [{ type: DialogTitleDirective, selector: "[vdrDialogTitle]" }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: FormFieldControlDirective, selector: "input, textarea, select" }, { type: DialogButtonsDirective, selector: "[vdrDialogButtons]" }], pipes: { "translate": i7.TranslatePipe, "async": i3.AsyncPipe, "stringToColor": StringToColorPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
10887
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ManageTagsDialogComponent, decorators: [{
11296
+ SelectToggleComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SelectToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11297
+ SelectToggleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: SelectToggleComponent, selector: "vdr-select-toggle", inputs: { size: "size", selected: "selected", hiddenWhenOff: "hiddenWhenOff", disabled: "disabled", label: "label" }, outputs: { selectedChange: "selectedChange" }, ngImport: i0, template: "<div\r\n class=\"toggle\"\r\n [class.hide-when-off]=\"hiddenWhenOff\"\r\n [class.disabled]=\"disabled\"\r\n [class.small]=\"size === 'small'\"\r\n [attr.tabindex]=\"disabled ? null : 0\"\r\n [class.selected]=\"selected\"\r\n (keydown.enter)=\"selectedChange.emit(!selected)\"\r\n (keydown.space)=\"$event.preventDefault(); selectedChange.emit(!selected)\"\r\n (click)=\"selectedChange.emit(!selected)\"\r\n>\r\n <clr-icon shape=\"check-circle\" [attr.size]=\"size === 'small' ? 24 : 32\"></clr-icon>\r\n</div>\r\n<div class=\"toggle-label\" [class.disabled]=\"disabled\" *ngIf=\"label\" (click)=\"selectedChange.emit(!selected)\">\r\n {{ label }}\r\n</div>\r\n", styles: [":host{display:flex;align-items:center;justify-content:center}.toggle{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;cursor:pointer;color:var(--color-grey-300);background-color:var(--color-component-bg-100);border-radius:50%;top:-12px;left:-12px;transition:opacity .2s,color .2s}.toggle.hide-when-off{opacity:0}.toggle.small{width:24px;height:24px}.toggle:not(.disabled):hover{color:var(--color-success-400);opacity:.9}.toggle.selected{opacity:1;color:var(--color-success-500)}.toggle.selected:not(.disabled):hover{color:var(--color-success-400);opacity:.9}.toggle:focus{outline:none;box-shadow:0 0 2px 2px var(--color-primary-500)}.toggle.disabled{cursor:default}.toggle-label{flex:1;margin-left:6px;text-align:left;font-size:12px}.toggle-label:not(.disabled){cursor:pointer}\n"], directives: [{ type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SelectToggleComponent, decorators: [{
10888
11299
  type: Component,
10889
- args: [{ selector: 'vdr-manage-tags-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template vdrDialogTitle>\r\n <span>{{ 'common.manage-tags' | translate }}</span>\r\n</ng-template>\r\n<p class=\"mt0 mb4\">{{ 'common.manage-tags-description' | translate }}</p>\r\n<ul class=\"tag-list\" *ngFor=\"let tag of allTags$ | async\">\r\n <li class=\"mb2 p1\" [class.to-delete]=\"markedAsDeleted(tag.id)\">\r\n <clr-icon shape=\"tag\" class=\"is-solid mr2\" [style.color]=\"tag.value | stringToColor\"></clr-icon>\r\n <input type=\"text\" (input)=\"updateTagValue(tag.id, $event.target.value)\" [value]=\"tag.value\" />\r\n <button class=\"icon-button\" (click)=\"toggleDelete(tag.id)\">\r\n <clr-icon shape=\"trash\" class=\"is-danger\" [class.is-solid]=\"markedAsDeleted(tag.id)\"></clr-icon>\r\n </button>\r\n </li>\r\n</ul>\r\n<ng-template vdrDialogButtons>\r\n <button type=\"submit\" (click)=\"resolveWith(false)\" class=\"btn btn-secondary\">\r\n {{ 'common.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"submit\"\r\n (click)=\"saveChanges()\"\r\n class=\"btn btn-primary\"\r\n [disabled]=\"!toUpdate.length && !toDelete.length\"\r\n >\r\n {{ 'common.update' | translate }}\r\n </button>\r\n</ng-template>\r\n", styles: [".tag-list{list-style-type:none}.tag-list li{display:flex;align-items:center}.tag-list li input{max-width:170px}.tag-list li.to-delete{opacity:.7;background-color:var(--color-component-bg-300)}.tag-list li.to-delete input{background-color:transparent!important}\n"] }]
10890
- }], ctorParameters: function () { return [{ type: DataService }]; } });
11300
+ args: [{ selector: 'vdr-select-toggle', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"toggle\"\r\n [class.hide-when-off]=\"hiddenWhenOff\"\r\n [class.disabled]=\"disabled\"\r\n [class.small]=\"size === 'small'\"\r\n [attr.tabindex]=\"disabled ? null : 0\"\r\n [class.selected]=\"selected\"\r\n (keydown.enter)=\"selectedChange.emit(!selected)\"\r\n (keydown.space)=\"$event.preventDefault(); selectedChange.emit(!selected)\"\r\n (click)=\"selectedChange.emit(!selected)\"\r\n>\r\n <clr-icon shape=\"check-circle\" [attr.size]=\"size === 'small' ? 24 : 32\"></clr-icon>\r\n</div>\r\n<div class=\"toggle-label\" [class.disabled]=\"disabled\" *ngIf=\"label\" (click)=\"selectedChange.emit(!selected)\">\r\n {{ label }}\r\n</div>\r\n", styles: [":host{display:flex;align-items:center;justify-content:center}.toggle{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;cursor:pointer;color:var(--color-grey-300);background-color:var(--color-component-bg-100);border-radius:50%;top:-12px;left:-12px;transition:opacity .2s,color .2s}.toggle.hide-when-off{opacity:0}.toggle.small{width:24px;height:24px}.toggle:not(.disabled):hover{color:var(--color-success-400);opacity:.9}.toggle.selected{opacity:1;color:var(--color-success-500)}.toggle.selected:not(.disabled):hover{color:var(--color-success-400);opacity:.9}.toggle:focus{outline:none;box-shadow:0 0 2px 2px var(--color-primary-500)}.toggle.disabled{cursor:default}.toggle-label{flex:1;margin-left:6px;text-align:left;font-size:12px}.toggle-label:not(.disabled){cursor:pointer}\n"] }]
11301
+ }], propDecorators: { size: [{
11302
+ type: Input
11303
+ }], selected: [{
11304
+ type: Input
11305
+ }], hiddenWhenOff: [{
11306
+ type: Input
11307
+ }], disabled: [{
11308
+ type: Input
11309
+ }], label: [{
11310
+ type: Input
11311
+ }], selectedChange: [{
11312
+ type: Output
11313
+ }] } });
10891
11314
 
10892
- class FocalPointControlComponent {
11315
+ /**
11316
+ * A control for setting the number of items per page in a paginated list.
11317
+ */
11318
+ class ItemsPerPageControlsComponent {
10893
11319
  constructor() {
10894
- this.visible = false;
10895
- this.editable = false;
10896
- this.fpx = 0.5;
10897
- this.fpy = 0.5;
10898
- this.focalPointChange = new EventEmitter();
10899
- }
10900
- get initialPosition() {
10901
- return this.focalPointToOffset(this.fpx == null ? 0.5 : this.fpx, this.fpy == null ? 0.5 : this.fpy);
10902
- }
10903
- onDragEnded(event) {
10904
- const { x, y } = this.getCurrentFocalPoint();
10905
- this.fpx = x;
10906
- this.fpy = y;
10907
- this.focalPointChange.emit({ x, y });
10908
- }
10909
- getCurrentFocalPoint() {
10910
- const { left: dotLeft, top: dotTop, width, height } = this.dot.nativeElement.getBoundingClientRect();
10911
- const { left: frameLeft, top: frameTop } = this.frame.nativeElement.getBoundingClientRect();
10912
- const xInPx = dotLeft - frameLeft + width / 2;
10913
- const yInPx = dotTop - frameTop + height / 2;
10914
- return {
10915
- x: xInPx / this.width,
10916
- y: yInPx / this.height,
10917
- };
10918
- }
10919
- focalPointToOffset(x, y) {
10920
- const { width, height } = this.dot.nativeElement.getBoundingClientRect();
10921
- return {
10922
- x: x * this.width - width / 2,
10923
- y: y * this.height - height / 2,
10924
- };
11320
+ this.itemsPerPage = 10;
11321
+ this.itemsPerPageChange = new EventEmitter();
10925
11322
  }
10926
11323
  }
10927
- FocalPointControlComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: FocalPointControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10928
- FocalPointControlComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: FocalPointControlComponent, selector: "vdr-focal-point-control", inputs: { visible: "visible", editable: "editable", width: "width", height: "height", fpx: "fpx", fpy: "fpy" }, outputs: { focalPointChange: "focalPointChange" }, host: { properties: { "style.width.px": "this.width", "style.height.px": "this.height" } }, viewQueries: [{ propertyName: "frame", first: true, predicate: ["frame"], descendants: true, static: true }, { propertyName: "dot", first: true, predicate: ["dot"], descendants: true, static: true }], ngImport: i0, template: "<ng-content></ng-content>\r\n<div class=\"frame\" #frame [style.width.px]=\"width\" [style.height.px]=\"height\">\r\n <div\r\n #dot\r\n class=\"dot\"\r\n [class.visible]=\"visible\"\r\n [class.editable]=\"editable\"\r\n cdkDrag\r\n [cdkDragDisabled]=\"!editable\"\r\n cdkDragBoundary=\".frame\"\r\n (cdkDragEnded)=\"onDragEnded($event)\"\r\n [cdkDragFreeDragPosition]=\"initialPosition\"\r\n ></div>\r\n</div>\r\n", styles: [":host{position:relative;display:block}.frame{position:absolute;top:0}.dot{width:20px;height:20px;border-radius:50%;border:2px solid white;position:absolute;visibility:hidden;transition:opacity .3s;box-shadow:0 0 4px 4px #0000006b}.dot.visible{visibility:visible;opacity:.7}.dot.editable{cursor:move;visibility:visible;opacity:1;animation:pulse;animation-duration:.5s;animation-iteration-count:4}@keyframes pulse{0%{border-color:#fff}50%{border-color:var(--color-warning-500)}to{border-color:#fff}}\n"], directives: [{ type: i3$1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10929
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: FocalPointControlComponent, decorators: [{
11324
+ ItemsPerPageControlsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ItemsPerPageControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11325
+ ItemsPerPageControlsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ItemsPerPageControlsComponent, selector: "vdr-items-per-page-controls", inputs: { itemsPerPage: "itemsPerPage" }, outputs: { itemsPerPageChange: "itemsPerPageChange" }, ngImport: i0, template: "<div class=\"select\">\r\n <select [ngModel]=\"itemsPerPage\" (change)=\"itemsPerPageChange.emit($event.target.value)\">\r\n <option [value]=\"10\">{{ 'common.items-per-page-option' | translate: { count: 10 } }}</option>\r\n <option [value]=\"25\">{{ 'common.items-per-page-option' | translate: { count: 25 } }}</option>\r\n <option [value]=\"50\">{{ 'common.items-per-page-option' | translate: { count: 50 } }}</option>\r\n <option [value]=\"100\">{{ 'common.items-per-page-option' | translate: { count: 100 } }}</option>\r\n </select>\r\n</div>\r\n", styles: [""], directives: [{ type: FormFieldControlDirective, selector: "input, textarea, select" }, { type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }], pipes: { "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11326
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ItemsPerPageControlsComponent, decorators: [{
10930
11327
  type: Component,
10931
- args: [{ selector: 'vdr-focal-point-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>\r\n<div class=\"frame\" #frame [style.width.px]=\"width\" [style.height.px]=\"height\">\r\n <div\r\n #dot\r\n class=\"dot\"\r\n [class.visible]=\"visible\"\r\n [class.editable]=\"editable\"\r\n cdkDrag\r\n [cdkDragDisabled]=\"!editable\"\r\n cdkDragBoundary=\".frame\"\r\n (cdkDragEnded)=\"onDragEnded($event)\"\r\n [cdkDragFreeDragPosition]=\"initialPosition\"\r\n ></div>\r\n</div>\r\n", styles: [":host{position:relative;display:block}.frame{position:absolute;top:0}.dot{width:20px;height:20px;border-radius:50%;border:2px solid white;position:absolute;visibility:hidden;transition:opacity .3s;box-shadow:0 0 4px 4px #0000006b}.dot.visible{visibility:visible;opacity:.7}.dot.editable{cursor:move;visibility:visible;opacity:1;animation:pulse;animation-duration:.5s;animation-iteration-count:4}@keyframes pulse{0%{border-color:#fff}50%{border-color:var(--color-warning-500)}to{border-color:#fff}}\n"] }]
10932
- }], propDecorators: { visible: [{
10933
- type: Input
10934
- }], editable: [{
11328
+ args: [{ selector: 'vdr-items-per-page-controls', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"select\">\r\n <select [ngModel]=\"itemsPerPage\" (change)=\"itemsPerPageChange.emit($event.target.value)\">\r\n <option [value]=\"10\">{{ 'common.items-per-page-option' | translate: { count: 10 } }}</option>\r\n <option [value]=\"25\">{{ 'common.items-per-page-option' | translate: { count: 25 } }}</option>\r\n <option [value]=\"50\">{{ 'common.items-per-page-option' | translate: { count: 50 } }}</option>\r\n <option [value]=\"100\">{{ 'common.items-per-page-option' | translate: { count: 100 } }}</option>\r\n </select>\r\n</div>\r\n", styles: [""] }]
11329
+ }], propDecorators: { itemsPerPage: [{
10935
11330
  type: Input
10936
- }], width: [{
10937
- type: HostBinding,
10938
- args: ['style.width.px']
10939
- }, {
11331
+ }], itemsPerPageChange: [{
11332
+ type: Output
11333
+ }] } });
11334
+
11335
+ class PaginationControlsComponent {
11336
+ constructor() {
11337
+ this.pageChange = new EventEmitter();
11338
+ }
11339
+ }
11340
+ PaginationControlsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: PaginationControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11341
+ PaginationControlsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: PaginationControlsComponent, selector: "vdr-pagination-controls", inputs: { id: "id", currentPage: "currentPage", itemsPerPage: "itemsPerPage", totalItems: "totalItems" }, outputs: { pageChange: "pageChange" }, ngImport: i0, template: "<pagination-template #p=\"paginationApi\" (pageChange)=\"pageChange.emit($event)\" [id]=\"id\">\r\n <ul>\r\n <li class=\"pagination-previous\">\r\n <a *ngIf=\"!p.isFirstPage()\" (click)=\"p.previous()\" (keyup.enter)=\"p.previous()\" tabindex=\"0\">\u00AB</a>\r\n <div *ngIf=\"p.isFirstPage()\">\u00AB</div>\r\n </li>\r\n\r\n <li *ngFor=\"let page of p.pages\">\r\n <a\r\n (click)=\"p.setCurrent(page.value)\"\r\n (keyup.enter)=\"p.setCurrent(page.value)\"\r\n *ngIf=\"p.getCurrent() !== page.value\"\r\n tabindex=\"0\"\r\n >\r\n {{ page.label }}\r\n </a>\r\n\r\n <div class=\"current\" *ngIf=\"p.getCurrent() === page.value\">{{ page.label }}</div>\r\n </li>\r\n\r\n <li class=\"pagination-next\">\r\n <a *ngIf=\"!p.isLastPage()\" (click)=\"p.next()\" (keyup.enter)=\"p.next()\" tabindex=\"0\">\u00BB</a>\r\n <div *ngIf=\"p.isLastPage()\">\u00BB</div>\r\n </li>\r\n </ul>\r\n</pagination-template>\r\n", styles: ["pagination-template{display:block}pagination-template ul{list-style-type:none;display:flex;justify-content:center}pagination-template li{transition:border-bottom-color .2s}pagination-template li>a{cursor:pointer}pagination-template li>a:hover,pagination-template li>a:focus{border-bottom-color:var(--color-grey-300);text-decoration:none}pagination-template li>a,pagination-template li>div{padding:3px 12px;display:block;border-bottom:3px solid transparent;-webkit-user-select:none;user-select:none}pagination-template li>div.current{border-bottom-color:var(--color-primary-500)}\n"], directives: [{ type: i1$5.PaginationControlsDirective, selector: "pagination-template,[pagination-template]", inputs: ["maxSize", "id"], outputs: ["pageChange", "pageBoundsCorrection"], exportAs: ["paginationApi"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11342
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: PaginationControlsComponent, decorators: [{
11343
+ type: Component,
11344
+ args: [{ selector: 'vdr-pagination-controls', changeDetection: ChangeDetectionStrategy.OnPush, template: "<pagination-template #p=\"paginationApi\" (pageChange)=\"pageChange.emit($event)\" [id]=\"id\">\r\n <ul>\r\n <li class=\"pagination-previous\">\r\n <a *ngIf=\"!p.isFirstPage()\" (click)=\"p.previous()\" (keyup.enter)=\"p.previous()\" tabindex=\"0\">\u00AB</a>\r\n <div *ngIf=\"p.isFirstPage()\">\u00AB</div>\r\n </li>\r\n\r\n <li *ngFor=\"let page of p.pages\">\r\n <a\r\n (click)=\"p.setCurrent(page.value)\"\r\n (keyup.enter)=\"p.setCurrent(page.value)\"\r\n *ngIf=\"p.getCurrent() !== page.value\"\r\n tabindex=\"0\"\r\n >\r\n {{ page.label }}\r\n </a>\r\n\r\n <div class=\"current\" *ngIf=\"p.getCurrent() === page.value\">{{ page.label }}</div>\r\n </li>\r\n\r\n <li class=\"pagination-next\">\r\n <a *ngIf=\"!p.isLastPage()\" (click)=\"p.next()\" (keyup.enter)=\"p.next()\" tabindex=\"0\">\u00BB</a>\r\n <div *ngIf=\"p.isLastPage()\">\u00BB</div>\r\n </li>\r\n </ul>\r\n</pagination-template>\r\n", styles: ["pagination-template{display:block}pagination-template ul{list-style-type:none;display:flex;justify-content:center}pagination-template li{transition:border-bottom-color .2s}pagination-template li>a{cursor:pointer}pagination-template li>a:hover,pagination-template li>a:focus{border-bottom-color:var(--color-grey-300);text-decoration:none}pagination-template li>a,pagination-template li>div{padding:3px 12px;display:block;border-bottom:3px solid transparent;-webkit-user-select:none;user-select:none}pagination-template li>div.current{border-bottom-color:var(--color-primary-500)}\n"] }]
11345
+ }], propDecorators: { id: [{
10940
11346
  type: Input
10941
- }], height: [{
10942
- type: HostBinding,
10943
- args: ['style.height.px']
10944
- }, {
11347
+ }], currentPage: [{
10945
11348
  type: Input
10946
- }], fpx: [{
11349
+ }], itemsPerPage: [{
10947
11350
  type: Input
10948
- }], fpy: [{
11351
+ }], totalItems: [{
10949
11352
  type: Input
10950
- }], focalPointChange: [{
11353
+ }], pageChange: [{
10951
11354
  type: Output
10952
- }], frame: [{
10953
- type: ViewChild,
10954
- args: ['frame', { static: true }]
10955
- }], dot: [{
10956
- type: ViewChild,
10957
- args: ['dot', { static: true }]
10958
11355
  }] } });
10959
11356
 
10960
- class TagSelectorComponent {
10961
- constructor(dataService) {
11357
+ /**
11358
+ * @description
11359
+ * Given an Asset object (an object with `preview` and optionally `focalPoint` properties), this pipe
11360
+ * returns a string with query parameters designed to work with the image resize capabilities of the
11361
+ * AssetServerPlugin.
11362
+ *
11363
+ * @example
11364
+ * ```HTML
11365
+ * <img [src]="asset | assetPreview:'tiny'" />
11366
+ * <img [src]="asset | assetPreview:150" />
11367
+ * ```
11368
+ *
11369
+ * @docsCategory pipes
11370
+ */
11371
+ class AssetPreviewPipe {
11372
+ transform(asset, preset = 'thumb') {
11373
+ if (!asset) {
11374
+ return '';
11375
+ }
11376
+ if (asset.preview == null || typeof asset.preview !== 'string') {
11377
+ throw new Error(`Expected an Asset, got ${JSON.stringify(asset)}`);
11378
+ }
11379
+ const fp = asset.focalPoint ? `&fpx=${asset.focalPoint.x}&fpy=${asset.focalPoint.y}` : '';
11380
+ if (Number.isNaN(Number(preset))) {
11381
+ return `${asset.preview}?preset=${preset}${fp}`;
11382
+ }
11383
+ else {
11384
+ return `${asset.preview}?w=${preset}&h=${preset}${fp}`;
11385
+ }
11386
+ }
11387
+ }
11388
+ AssetPreviewPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetPreviewPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
11389
+ AssetPreviewPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetPreviewPipe, name: "assetPreview" });
11390
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetPreviewPipe, decorators: [{
11391
+ type: Pipe,
11392
+ args: [{
11393
+ name: 'assetPreview',
11394
+ }]
11395
+ }] });
11396
+
11397
+ class ProductMultiSelectorDialogComponent {
11398
+ constructor(dataService, changeDetector) {
10962
11399
  this.dataService = dataService;
11400
+ this.changeDetector = changeDetector;
11401
+ this.mode = 'product';
11402
+ this.initialSelectionIds = [];
11403
+ this.searchTerm$ = new BehaviorSubject('');
11404
+ this.searchFacetValueIds$ = new BehaviorSubject([]);
11405
+ this.paginationConfig = {
11406
+ currentPage: 1,
11407
+ itemsPerPage: 25,
11408
+ totalItems: 1,
11409
+ };
11410
+ this.paginationConfig$ = new BehaviorSubject(this.paginationConfig);
10963
11411
  }
10964
11412
  ngOnInit() {
10965
- this.allTags$ = this.dataService.product
10966
- .getTagList()
10967
- .mapStream(data => data.tags.items.map(i => i.value));
11413
+ const idFn = this.mode === 'product'
11414
+ ? (a, b) => a.productId === b.productId
11415
+ : (a, b) => a.productVariantId === b.productVariantId;
11416
+ this.selectionManager = new SelectionManager({
11417
+ multiSelect: true,
11418
+ itemsAreEqual: idFn,
11419
+ additiveMode: true,
11420
+ });
11421
+ const searchQueryResult = this.dataService.product.searchProducts('', this.paginationConfig.itemsPerPage, 0);
11422
+ const result$ = combineLatest(this.searchTerm$, this.searchFacetValueIds$, this.paginationConfig$).subscribe(([term, facetValueIds, pagination]) => {
11423
+ const take = +pagination.itemsPerPage;
11424
+ const skip = (pagination.currentPage - 1) * take;
11425
+ return searchQueryResult.ref.refetch({
11426
+ input: { skip, take, term, facetValueIds, groupByProduct: this.mode === 'product' },
11427
+ });
11428
+ });
11429
+ this.items$ = searchQueryResult.stream$.pipe(tap(data => {
11430
+ this.paginationConfig.totalItems = data.search.totalItems;
11431
+ this.selectionManager.setCurrentItems(data.search.items);
11432
+ }), map(data => data.search.items));
11433
+ this.facetValues$ = searchQueryResult.stream$.pipe(map(data => data.search.facetValues));
11434
+ if (this.initialSelectionIds.length) {
11435
+ if (this.mode === 'product') {
11436
+ this.dataService.product
11437
+ .getProducts({
11438
+ filter: {
11439
+ id: {
11440
+ in: this.initialSelectionIds,
11441
+ },
11442
+ },
11443
+ })
11444
+ .single$.subscribe(({ products }) => {
11445
+ this.selectionManager.selectMultiple(products.items.map(product => ({
11446
+ productId: product.id,
11447
+ productName: product.name,
11448
+ })));
11449
+ this.changeDetector.markForCheck();
11450
+ });
11451
+ }
11452
+ else {
11453
+ this.dataService.product
11454
+ .getProductVariants({
11455
+ filter: {
11456
+ id: {
11457
+ in: this.initialSelectionIds,
11458
+ },
11459
+ },
11460
+ })
11461
+ .single$.subscribe(({ productVariants }) => {
11462
+ this.selectionManager.selectMultiple(productVariants.items.map(variant => ({
11463
+ productVariantId: variant.id,
11464
+ productVariantName: variant.name,
11465
+ })));
11466
+ this.changeDetector.markForCheck();
11467
+ });
11468
+ }
11469
+ }
10968
11470
  }
10969
- addTagFn(val) {
10970
- return val;
11471
+ trackByFn(index, item) {
11472
+ return item.productId;
10971
11473
  }
10972
- registerOnChange(fn) {
10973
- this.onChange = fn;
11474
+ setSearchTerm(term) {
11475
+ this.searchTerm$.next(term);
10974
11476
  }
10975
- registerOnTouched(fn) {
10976
- this.onTouch = fn;
11477
+ setFacetValueIds(ids) {
11478
+ this.searchFacetValueIds$.next(ids);
10977
11479
  }
10978
- setDisabledState(isDisabled) {
10979
- this.disabled = isDisabled;
11480
+ toggleSelection(item, event) {
11481
+ this.selectionManager.toggleSelection(item, event);
10980
11482
  }
10981
- writeValue(obj) {
10982
- if (Array.isArray(obj)) {
10983
- this._value = obj;
10984
- }
11483
+ clearSelection() {
11484
+ this.selectionManager.selectMultiple([]);
10985
11485
  }
10986
- valueChanged(event) {
10987
- this.onChange(event);
11486
+ isSelected(item) {
11487
+ return this.selectionManager.isSelected(item);
11488
+ }
11489
+ entityInfoClick(event) {
11490
+ event.preventDefault();
11491
+ event.stopPropagation();
11492
+ }
11493
+ pageChange(page) {
11494
+ this.paginationConfig.currentPage = page;
11495
+ this.paginationConfig$.next(this.paginationConfig);
11496
+ }
11497
+ itemsPerPageChange(itemsPerPage) {
11498
+ this.paginationConfig.itemsPerPage = itemsPerPage;
11499
+ this.paginationConfig$.next(this.paginationConfig);
11500
+ }
11501
+ select() {
11502
+ this.resolveWith(this.selectionManager.selection);
11503
+ }
11504
+ cancel() {
11505
+ this.resolveWith();
10988
11506
  }
10989
11507
  }
10990
- TagSelectorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: TagSelectorComponent, deps: [{ token: DataService }], target: i0.ɵɵFactoryTarget.Component });
10991
- TagSelectorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: TagSelectorComponent, selector: "vdr-tag-selector", inputs: { placeholder: "placeholder" }, providers: [
10992
- {
10993
- provide: NG_VALUE_ACCESSOR,
10994
- useExisting: TagSelectorComponent,
10995
- multi: true,
10996
- },
10997
- ], ngImport: i0, template: "<ng-select\r\n [addTag]=\"addTagFn\"\r\n [multiple]=\"true\"\r\n [ngModel]=\"_value\"\r\n [clearable]=\"true\"\r\n [searchable]=\"true\"\r\n [disabled]=\"disabled\"\r\n [placeholder]=\"placeholder\"\r\n (change)=\"valueChanged($event)\"\r\n>\r\n <ng-template ng-label-tmp let-tag=\"item\" let-clear=\"clear\">\r\n <vdr-chip [colorFrom]=\"tag\" icon=\"close\" (iconClick)=\"clear(tag)\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag }}</vdr-chip>\r\n </ng-template>\r\n <ng-option *ngFor=\"let tag of allTags$ | async\" [value]=\"tag\">\r\n <vdr-chip [colorFrom]=\"tag\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag }}</vdr-chip>\r\n </ng-option>\r\n</ng-select>\r\n", styles: [":host{display:block;margin-top:12px;position:relative}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background:none;margin:0}:host ::ng-deep .ng-dropdown-panel-items div.ng-option:last-child{display:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border:none;padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-left:8px}\n"], components: [{ type: i2$1.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { type: ChipComponent, selector: "vdr-chip", inputs: ["icon", "invert", "colorFrom", "colorType"], outputs: ["iconClick"] }, { type: i2$1.NgOptionComponent, selector: "ng-option", inputs: ["value", "disabled"] }], directives: [{ type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i2$1.NgLabelTemplateDirective, selector: "[ng-label-tmp]" }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i3.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
10998
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: TagSelectorComponent, decorators: [{
11508
+ ProductMultiSelectorDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductMultiSelectorDialogComponent, deps: [{ token: DataService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
11509
+ ProductMultiSelectorDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ProductMultiSelectorDialogComponent, selector: "vdr-product-multi-selector-dialog", ngImport: i0, template: "<ng-template vdrDialogTitle>\r\n <div class=\"title-row\">\r\n <span *ngIf=\"mode === 'product'\">{{ 'common.select-products' | translate }}</span>\r\n <span *ngIf=\"mode === 'variant'\">{{ 'common.select-variants' | translate }}</span>\r\n </div>\r\n</ng-template>\r\n<vdr-product-search-input\r\n #productSearchInputComponent\r\n [facetValueResults]=\"facetValues$ | async\"\r\n (searchTermChange)=\"setSearchTerm($event)\"\r\n (facetValueChange)=\"setFacetValueIds($event)\"\r\n></vdr-product-search-input>\r\n<div class=\"flex-wrapper\">\r\n <div class=\"gallery\">\r\n <div\r\n class=\"card\"\r\n *ngFor=\"let item of (items$ | async) || [] | paginate: paginationConfig; trackBy: trackByFn\"\r\n (click)=\"toggleSelection(item, $event)\"\r\n [class.selected]=\"isSelected(item)\"\r\n >\r\n <div class=\"card-img\">\r\n <vdr-select-toggle\r\n [selected]=\"isSelected(item)\"\r\n [disabled]=\"true\"\r\n [hiddenWhenOff]=\"true\"\r\n ></vdr-select-toggle>\r\n <img\r\n [src]=\"\r\n (mode === 'product'\r\n ? item.productAsset\r\n : item.productVariantAsset || item.productAsset\r\n ) | assetPreview: 'thumb'\r\n \"\r\n />\r\n </div>\r\n <div class=\"detail\">\r\n <span [title]=\"mode === 'product' ? item.productName : item.productVariantName\">{{\r\n mode === 'product' ? item.productName : item.productVariantName\r\n }}</span>\r\n <div *ngIf=\"mode === 'variant'\"><small>{{ item.sku }}</small></div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"selection\">\r\n <div class=\"m2 flex center\">\r\n <div>\r\n {{ 'common.items-selected-count' | translate: { count: selectionManager.selection.length } }}\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <button class=\"btn btn-sm btn-link\" (click)=\"clearSelection()\">\r\n <cds-icon shape=\"times\"></cds-icon> {{ 'common.clear-selection' | translate }}\r\n </button>\r\n </div>\r\n <div class=\"selected-items\">\r\n <div *ngFor=\"let item of selectionManager.selection\" class=\"flex item-row\">\r\n <div class=\"\">{{ mode === 'product' ? item.productName : item.productVariantName }}</div>\r\n <div class=\"flex-spacer\"></div>\r\n <div>\r\n <button class=\"icon-button\" (click)=\"toggleSelection(item, $event)\">\r\n <cds-icon shape=\"times\"></cds-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"paging-controls\">\r\n <vdr-items-per-page-controls\r\n [itemsPerPage]=\"paginationConfig.itemsPerPage\"\r\n (itemsPerPageChange)=\"itemsPerPageChange($event)\"\r\n ></vdr-items-per-page-controls>\r\n\r\n <vdr-pagination-controls\r\n [currentPage]=\"paginationConfig.currentPage\"\r\n [itemsPerPage]=\"paginationConfig.itemsPerPage\"\r\n [totalItems]=\"paginationConfig.totalItems\"\r\n (pageChange)=\"pageChange($event)\"\r\n ></vdr-pagination-controls>\r\n</div>\r\n\r\n<ng-template vdrDialogButtons>\r\n <button type=\"button\" class=\"btn\" (click)=\"cancel()\">{{ 'common.cancel' | translate }}</button>\r\n <button\r\n type=\"submit\"\r\n (click)=\"select()\"\r\n class=\"btn btn-primary\"\r\n [disabled]=\"selectionManager.selection.length === 0\"\r\n >\r\n {{ 'common.select-items-with-count' | translate: { count: selectionManager.selection.length } }}\r\n </button>\r\n</ng-template>\r\n", styles: [":host{display:flex;flex-direction:column;flex-direction:1;height:70vh}.flex-wrapper{display:flex;overflow-y:hidden}.gallery{flex:1;display:grid;grid-template-columns:repeat(auto-fill,125px);grid-template-rows:repeat(auto-fill,200px);grid-gap:10px 20px;padding-left:12px;padding-top:12px;padding-bottom:64px;overflow-y:auto}.gallery .card:hover{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.detail{margin:0 3px;font-size:12px;line-height:.8rem}vdr-select-toggle{position:absolute;top:-12px;left:-12px}vdr-select-toggle ::ng-deep .toggle{box-shadow:0 5px 5px -4px #000000bf}.card.selected{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.card.selected .selected-checkbox{opacity:1}.selection{width:23vw;max-width:400px;padding:6px;display:flex;flex-direction:column}.selection .selected-items{flex:1;overflow-y:auto}.selection .selected-items .item-row{padding-left:3px}.selection .selected-items .item-row:hover{background-color:var(--color-component-bg-200)}.paging-controls{display:flex;align-items:center;justify-content:space-between}\n"], components: [{ type: ProductSearchInputComponent, selector: "vdr-product-search-input", inputs: ["facetValueResults"], outputs: ["searchTermChange", "facetValueChange"] }, { type: SelectToggleComponent, selector: "vdr-select-toggle", inputs: ["size", "selected", "hiddenWhenOff", "disabled", "label"], outputs: ["selectedChange"] }, { type: ItemsPerPageControlsComponent, selector: "vdr-items-per-page-controls", inputs: ["itemsPerPage"], outputs: ["itemsPerPageChange"] }, { type: PaginationControlsComponent, selector: "vdr-pagination-controls", inputs: ["id", "currentPage", "itemsPerPage", "totalItems"], outputs: ["pageChange"] }], directives: [{ type: DialogTitleDirective, selector: "[vdrDialogTitle]" }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$3.ClrDatagridItemsTrackBy, selector: "[ngForTrackBy]", inputs: ["ngForTrackBy"] }, { type: i1$3.CdsIconCustomTag, selector: "cds-icon" }, { type: DialogButtonsDirective, selector: "[vdrDialogButtons]" }], pipes: { "translate": i7.TranslatePipe, "async": i3.AsyncPipe, "paginate": i1$5.PaginatePipe, "assetPreview": AssetPreviewPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11510
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductMultiSelectorDialogComponent, decorators: [{
10999
11511
  type: Component,
11000
- args: [{ selector: 'vdr-tag-selector', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
11001
- {
11002
- provide: NG_VALUE_ACCESSOR,
11003
- useExisting: TagSelectorComponent,
11004
- multi: true,
11005
- },
11006
- ], template: "<ng-select\r\n [addTag]=\"addTagFn\"\r\n [multiple]=\"true\"\r\n [ngModel]=\"_value\"\r\n [clearable]=\"true\"\r\n [searchable]=\"true\"\r\n [disabled]=\"disabled\"\r\n [placeholder]=\"placeholder\"\r\n (change)=\"valueChanged($event)\"\r\n>\r\n <ng-template ng-label-tmp let-tag=\"item\" let-clear=\"clear\">\r\n <vdr-chip [colorFrom]=\"tag\" icon=\"close\" (iconClick)=\"clear(tag)\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag }}</vdr-chip>\r\n </ng-template>\r\n <ng-option *ngFor=\"let tag of allTags$ | async\" [value]=\"tag\">\r\n <vdr-chip [colorFrom]=\"tag\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag }}</vdr-chip>\r\n </ng-option>\r\n</ng-select>\r\n", styles: [":host{display:block;margin-top:12px;position:relative}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background:none;margin:0}:host ::ng-deep .ng-dropdown-panel-items div.ng-option:last-child{display:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border:none;padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-left:8px}\n"] }]
11007
- }], ctorParameters: function () { return [{ type: DataService }]; }, propDecorators: { placeholder: [{
11008
- type: Input
11009
- }] } });
11512
+ args: [{ selector: 'vdr-product-multi-selector-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template vdrDialogTitle>\r\n <div class=\"title-row\">\r\n <span *ngIf=\"mode === 'product'\">{{ 'common.select-products' | translate }}</span>\r\n <span *ngIf=\"mode === 'variant'\">{{ 'common.select-variants' | translate }}</span>\r\n </div>\r\n</ng-template>\r\n<vdr-product-search-input\r\n #productSearchInputComponent\r\n [facetValueResults]=\"facetValues$ | async\"\r\n (searchTermChange)=\"setSearchTerm($event)\"\r\n (facetValueChange)=\"setFacetValueIds($event)\"\r\n></vdr-product-search-input>\r\n<div class=\"flex-wrapper\">\r\n <div class=\"gallery\">\r\n <div\r\n class=\"card\"\r\n *ngFor=\"let item of (items$ | async) || [] | paginate: paginationConfig; trackBy: trackByFn\"\r\n (click)=\"toggleSelection(item, $event)\"\r\n [class.selected]=\"isSelected(item)\"\r\n >\r\n <div class=\"card-img\">\r\n <vdr-select-toggle\r\n [selected]=\"isSelected(item)\"\r\n [disabled]=\"true\"\r\n [hiddenWhenOff]=\"true\"\r\n ></vdr-select-toggle>\r\n <img\r\n [src]=\"\r\n (mode === 'product'\r\n ? item.productAsset\r\n : item.productVariantAsset || item.productAsset\r\n ) | assetPreview: 'thumb'\r\n \"\r\n />\r\n </div>\r\n <div class=\"detail\">\r\n <span [title]=\"mode === 'product' ? item.productName : item.productVariantName\">{{\r\n mode === 'product' ? item.productName : item.productVariantName\r\n }}</span>\r\n <div *ngIf=\"mode === 'variant'\"><small>{{ item.sku }}</small></div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"selection\">\r\n <div class=\"m2 flex center\">\r\n <div>\r\n {{ 'common.items-selected-count' | translate: { count: selectionManager.selection.length } }}\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <button class=\"btn btn-sm btn-link\" (click)=\"clearSelection()\">\r\n <cds-icon shape=\"times\"></cds-icon> {{ 'common.clear-selection' | translate }}\r\n </button>\r\n </div>\r\n <div class=\"selected-items\">\r\n <div *ngFor=\"let item of selectionManager.selection\" class=\"flex item-row\">\r\n <div class=\"\">{{ mode === 'product' ? item.productName : item.productVariantName }}</div>\r\n <div class=\"flex-spacer\"></div>\r\n <div>\r\n <button class=\"icon-button\" (click)=\"toggleSelection(item, $event)\">\r\n <cds-icon shape=\"times\"></cds-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div class=\"paging-controls\">\r\n <vdr-items-per-page-controls\r\n [itemsPerPage]=\"paginationConfig.itemsPerPage\"\r\n (itemsPerPageChange)=\"itemsPerPageChange($event)\"\r\n ></vdr-items-per-page-controls>\r\n\r\n <vdr-pagination-controls\r\n [currentPage]=\"paginationConfig.currentPage\"\r\n [itemsPerPage]=\"paginationConfig.itemsPerPage\"\r\n [totalItems]=\"paginationConfig.totalItems\"\r\n (pageChange)=\"pageChange($event)\"\r\n ></vdr-pagination-controls>\r\n</div>\r\n\r\n<ng-template vdrDialogButtons>\r\n <button type=\"button\" class=\"btn\" (click)=\"cancel()\">{{ 'common.cancel' | translate }}</button>\r\n <button\r\n type=\"submit\"\r\n (click)=\"select()\"\r\n class=\"btn btn-primary\"\r\n [disabled]=\"selectionManager.selection.length === 0\"\r\n >\r\n {{ 'common.select-items-with-count' | translate: { count: selectionManager.selection.length } }}\r\n </button>\r\n</ng-template>\r\n", styles: [":host{display:flex;flex-direction:column;flex-direction:1;height:70vh}.flex-wrapper{display:flex;overflow-y:hidden}.gallery{flex:1;display:grid;grid-template-columns:repeat(auto-fill,125px);grid-template-rows:repeat(auto-fill,200px);grid-gap:10px 20px;padding-left:12px;padding-top:12px;padding-bottom:64px;overflow-y:auto}.gallery .card:hover{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.detail{margin:0 3px;font-size:12px;line-height:.8rem}vdr-select-toggle{position:absolute;top:-12px;left:-12px}vdr-select-toggle ::ng-deep .toggle{box-shadow:0 5px 5px -4px #000000bf}.card.selected{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.card.selected .selected-checkbox{opacity:1}.selection{width:23vw;max-width:400px;padding:6px;display:flex;flex-direction:column}.selection .selected-items{flex:1;overflow-y:auto}.selection .selected-items .item-row{padding-left:3px}.selection .selected-items .item-row:hover{background-color:var(--color-component-bg-200)}.paging-controls{display:flex;align-items:center;justify-content:space-between}\n"] }]
11513
+ }], ctorParameters: function () { return [{ type: DataService }, { type: i0.ChangeDetectorRef }]; } });
11010
11514
 
11011
- class HelpTooltipComponent {
11515
+ class ProductMultiSelectorFormInputComponent {
11516
+ constructor(modalService, dataService, changeDetector) {
11517
+ this.modalService = modalService;
11518
+ this.dataService = dataService;
11519
+ this.changeDetector = changeDetector;
11520
+ this.mode = 'product';
11521
+ this.isListInput = true;
11522
+ }
11523
+ ngOnInit() {
11524
+ var _a, _b;
11525
+ this.mode = (_b = (_a = this.config.ui) === null || _a === void 0 ? void 0 : _a.selectionMode) !== null && _b !== void 0 ? _b : 'product';
11526
+ }
11527
+ select() {
11528
+ this.modalService
11529
+ .fromComponent(ProductMultiSelectorDialogComponent, {
11530
+ size: 'xl',
11531
+ locals: {
11532
+ mode: this.mode,
11533
+ initialSelectionIds: this.formControl.value,
11534
+ },
11535
+ })
11536
+ .subscribe(selection => {
11537
+ if (selection) {
11538
+ this.formControl.setValue(selection.map(item => this.mode === 'product' ? item.productId : item.productVariantId));
11539
+ this.changeDetector.markForCheck();
11540
+ }
11541
+ });
11542
+ }
11012
11543
  }
11013
- HelpTooltipComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: HelpTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11014
- HelpTooltipComponentcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: HelpTooltipComponent, selector: "vdr-help-tooltip", inputs: { content: "content", position: "position" }, ngImport: i0, template: "<clr-tooltip>\r\n <clr-icon clrTooltipTrigger shape=\"help\" size=\"14\"></clr-icon>\r\n <clr-tooltip-content [clrPosition]=\"position\" clrSize=\"md\" *clrIfOpen>\r\n <span>{{ content }}</span>\r\n </clr-tooltip-content>\r\n</clr-tooltip>\r\n", styles: ["clr-tooltip{display:inline-flex}\n"], components: [{ type: i1$3.ClrTooltip, selector: "clr-tooltip" }, { type: i1$3.ClrTooltipContent, selector: "clr-tooltip-content", inputs: ["id", "clrPosition", "clrSize"] }], directives: [{ type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i1$3.ClrTooltipTrigger, selector: "[clrTooltipTrigger]" }, { type: i1$3.ClrIfOpen, selector: "[clrIfOpen]", inputs: ["clrIfOpen"], outputs: ["clrIfOpenChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11015
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: HelpTooltipComponent, decorators: [{
11544
+ ProductMultiSelectorFormInputComponent.id = 'product-multi-form-input';
11545
+ ProductMultiSelectorFormInputComponentfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductMultiSelectorFormInputComponent, deps: [{ token: ModalService }, { token: DataService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
11546
+ ProductMultiSelectorFormInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ProductMultiSelectorFormInputComponent, selector: "vdr-product-multi-selector-form-input", inputs: { config: "config", formControl: "formControl", readonly: "readonly" }, ngImport: i0, template: "<div class=\"flex\">\r\n <button (click)=\"select()\" class=\"btn btn-sm btn-secondary\">\r\n {{ 'common.items-selected-count' | translate: { count: formControl.value?.length ?? 0 } }}...\r\n </button>\r\n</div>\r\n", styles: [""], pipes: { "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11547
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductMultiSelectorFormInputComponent, decorators: [{
11016
11548
  type: Component,
11017
- args: [{ selector: 'vdr-help-tooltip', changeDetection: ChangeDetectionStrategy.OnPush, template: "<clr-tooltip>\r\n <clr-icon clrTooltipTrigger shape=\"help\" size=\"14\"></clr-icon>\r\n <clr-tooltip-content [clrPosition]=\"position\" clrSize=\"md\" *clrIfOpen>\r\n <span>{{ content }}</span>\r\n </clr-tooltip-content>\r\n</clr-tooltip>\r\n", styles: ["clr-tooltip{display:inline-flex}\n"] }]
11018
- }], propDecorators: { content: [{
11549
+ args: [{ selector: 'vdr-product-multi-selector-form-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex\">\r\n <button (click)=\"select()\" class=\"btn btn-sm btn-secondary\">\r\n {{ 'common.items-selected-count' | translate: { count: formControl.value?.length ?? 0 } }}...\r\n </button>\r\n</div>\r\n", styles: [""] }]
11550
+ }], ctorParameters: function () { return [{ type: ModalService }, { type: DataService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { config: [{
11019
11551
  type: Input
11020
- }], position: [{
11552
+ }], formControl: [{
11553
+ type: Input
11554
+ }], readonly: [{
11021
11555
  type: Input
11022
11556
  }] } });
11023
11557
 
11024
11558
  /**
11025
- * A form field wrapper which handles the correct layout and validation error display for
11026
- * a form control.
11559
+ * @description
11560
+ * A component for selecting product variants via an autocomplete-style select input.
11561
+ *
11562
+ * @example
11563
+ * ```HTML
11564
+ * <vdr-product-variant-selector
11565
+ * (productSelected)="selectResult($event)"></vdr-product-selector>
11566
+ * ```
11567
+ *
11568
+ * @docsCategory components
11027
11569
  */
11028
- class FormFieldComponent {
11029
- constructor() {
11030
- /**
11031
- * A map of error message codes (required, pattern etc.) to messages to display
11032
- * when those errors are present.
11033
- */
11034
- this.errors = {};
11035
- /**
11036
- * If set to true, the input will be initially set to "readOnly", and an "edit" button
11037
- * will be displayed which allows the field to be edited.
11038
- */
11039
- this.readOnlyToggle = false;
11040
- this.isReadOnly = false;
11570
+ class ProductVariantSelectorComponent {
11571
+ constructor(dataService) {
11572
+ this.dataService = dataService;
11573
+ this.searchInput$ = new Subject();
11574
+ this.searchLoading = false;
11575
+ this.productSelected = new EventEmitter();
11041
11576
  }
11042
11577
  ngOnInit() {
11043
- if (this.readOnlyToggle) {
11044
- this.isReadOnly = true;
11045
- this.setReadOnly(true);
11046
- }
11047
- this.isReadOnly = this.readOnlyToggle;
11048
- }
11049
- setReadOnly(value) {
11050
- this.formFieldControl.setReadOnly(value);
11051
- this.isReadOnly = value;
11578
+ this.initSearchResults();
11052
11579
  }
11053
- getErrorMessage() {
11054
- if (!this.formFieldControl || !this.formFieldControl.formControlName) {
11055
- return;
11056
- }
11057
- const errors = this.formFieldControl.formControlName.errors;
11058
- if (errors) {
11059
- for (const errorKey of Object.keys(errors)) {
11060
- if (this.errors[errorKey]) {
11061
- return this.errors[errorKey];
11062
- }
11580
+ initSearchResults() {
11581
+ const searchItems$ = this.searchInput$.pipe(debounceTime(200), distinctUntilChanged(), tap(() => (this.searchLoading = true)), switchMap(term => {
11582
+ if (!term) {
11583
+ return of([]);
11063
11584
  }
11585
+ return this.dataService.product
11586
+ .productSelectorSearch(term, 10)
11587
+ .mapSingle(result => result.search.items);
11588
+ }), tap(() => (this.searchLoading = false)));
11589
+ const clear$ = this.productSelected.pipe(mapTo([]));
11590
+ this.searchResults$ = concat(of([]), merge(searchItems$, clear$));
11591
+ }
11592
+ selectResult(product) {
11593
+ if (product) {
11594
+ this.productSelected.emit(product);
11595
+ this.ngSelect.clearModel();
11064
11596
  }
11065
11597
  }
11066
11598
  }
11067
- FormFieldComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: FormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11068
- FormFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: FormFieldComponent, selector: "vdr-form-field", inputs: { label: "label", for: "for", tooltip: "tooltip", errors: "errors", readOnlyToggle: "readOnlyToggle" }, queries: [{ propertyName: "formFieldControl", first: true, predicate: FormFieldControlDirective, descendants: true, static: true }], ngImport: i0, template: "<div\r\n class=\"form-group\"\r\n [class.no-label]=\"!label\"\r\n [class.clr-error]=\"formFieldControl?.formControlName?.invalid\"\r\n>\r\n <label *ngIf=\"label\" [for]=\"for\" class=\"clr-control-label\">\r\n {{ label }}\r\n <vdr-help-tooltip *ngIf=\"tooltip\" [content]=\"tooltip\"></vdr-help-tooltip>\r\n </label>\r\n <label\r\n [for]=\"for\"\r\n aria-haspopup=\"true\"\r\n role=\"tooltip\"\r\n [class.invalid]=\"formFieldControl?.touched && !formFieldControl?.valid\"\r\n class=\"tooltip tooltip-validation tooltip-sm tooltip-top-left\"\r\n >\r\n <div class=\"input-row\" [class.has-toggle]=\"readOnlyToggle\">\r\n <ng-content></ng-content>\r\n <button\r\n *ngIf=\"readOnlyToggle\"\r\n type=\"button\"\r\n [disabled]=\"!isReadOnly\"\r\n [title]=\"'common.edit-field' | translate\"\r\n class=\"btn btn-icon edit-button\"\r\n (click)=\"setReadOnly(false)\"\r\n >\r\n <clr-icon shape=\"edit\"></clr-icon>\r\n </button>\r\n </div>\r\n <div class=\"clr-subtext\" *ngIf=\"getErrorMessage()\">{{ getErrorMessage() }}</div>\r\n <span class=\"tooltip-content\">{{ label }} is required.</span>\r\n </label>\r\n</div>\r\n", styles: [":host{display:block}:host .form-group>label:first-child{top:6px}:host .form-group>label:nth-of-type(2){flex:1;max-width:20rem}:host .form-group>label:nth-of-type(2) ::ng-deep>*:not(.tooltip-content){width:100%}:host .form-group .tooltip-validation{height:initial}:host .form-group.no-label{margin:-6px 0 0;padding:0;justify-content:center}:host .form-group.no-label>label{position:relative;justify-content:center}:host .form-group.no-label .input-row{justify-content:center}:host .input-row{display:flex}:host .input-row ::ng-deep input{flex:1}:host .input-row ::ng-deep input[disabled]{background-color:var(--color-component-bg-200)}:host .input-row button.edit-button{margin:0;border-radius:0 3px 3px 0}:host .input-row.has-toggle ::ng-deep input{border-top-right-radius:0!important;border-bottom-right-radius:0!important;border-right:none}:host .input-row ::ng-deep clr-toggle-wrapper{margin-top:8px}.tooltip.tooltip-validation.invalid:before{position:absolute;content:\"\";height:.666667rem;width:.666667rem;top:.125rem;right:.25rem;background-image:url(data:image/svg+xml;charset=utf8,%3Csvg%20version%3D%221.1%22%20viewBox%3D%225%205%2026%2026%22%20preserveAspectRatio%3D%22xMidYMid%20meet%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%3Cdefs%3E%3Cstyle%3E.clr-i-outline%7Bfill%3A%23a32100%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctitle%3Eexclamation-circle-line%3C%2Ftitle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20class%3D%22clr-i-outline%20clr-i-outline-path-1%22%20d%3D%22M18%2C6A12%2C12%2C0%2C1%2C0%2C30%2C18%2C12%2C12%2C0%2C0%2C0%2C18%2C6Zm0%2C22A10%2C10%2C0%2C1%2C1%2C28%2C18%2C10%2C10%2C0%2C0%2C1%2C18%2C28Z%22%3E%3C%2Fpath%3E%3Cpath%20class%3D%22clr-i-outline%20clr-i-outline-path-2%22%20d%3D%22M18%2C20.07a1.3%2C1.3%2C0%2C0%2C1-1.3-1.3v-6a1.3%2C1.3%2C0%2C1%2C1%2C2.6%2C0v6A1.3%2C1.3%2C0%2C0%2C1%2C18%2C20.07Z%22%3E%3C%2Fpath%3E%3Ccircle%20class%3D%22clr-i-outline%20clr-i-outline-path-3%22%20cx%3D%2217.95%22%20cy%3D%2223.02%22%20r%3D%221.5%22%3E%3C%2Fcircle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fsvg%3E);background-repeat:no-repeat;background-size:contain;vertical-align:middle;margin:0}.tooltip.tooltip-sm>.tooltip-content,.tooltip .tooltip-content.tooltip-sm{width:5rem}.tooltip:hover>.tooltip-content{right:12px;margin-bottom:0}.tooltip:not(.invalid):hover>.tooltip-content{display:none}\n"], components: [{ type: HelpTooltipComponent, selector: "vdr-help-tooltip", inputs: ["content", "position"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$3.ClrLabel, selector: "label", inputs: ["for"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }], pipes: { "translate": i7.TranslatePipe } });
11069
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: FormFieldComponent, decorators: [{
11599
+ ProductVariantSelectorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductVariantSelectorComponent, deps: [{ token: DataService }], target: i0.ɵɵFactoryTarget.Component });
11600
+ ProductVariantSelectorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ProductVariantSelectorComponent, selector: "vdr-product-variant-selector", outputs: { productSelected: "productSelected" }, viewQueries: [{ propertyName: "ngSelect", first: true, predicate: ["autoComplete"], descendants: true, static: true }], ngImport: i0, template: "<ng-select\r\n #autoComplete\r\n [items]=\"searchResults$ | async\"\r\n [addTag]=\"false\"\r\n [multiple]=\"false\"\r\n [hideSelected]=\"true\"\r\n [loading]=\"searchLoading\"\r\n [typeahead]=\"searchInput$\"\r\n [appendTo]=\"'body'\"\r\n [placeholder]=\"'settings.search-by-product-name-or-sku' | translate\"\r\n (change)=\"selectResult($event)\"\r\n>\r\n <ng-template ng-option-tmp let-item=\"item\">\r\n <img [src]=\"item.productAsset | assetPreview: 32\">\r\n {{ item.productVariantName }}\r\n <small class=\"sku\">{{ item.sku }}</small>\r\n </ng-template>\r\n</ng-select>\r\n", styles: [":host{display:block}.sku{margin-left:12px;color:var(--color-grey-500)}\n"], components: [{ type: i2$1.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }], directives: [{ type: i2$1.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }], pipes: { "async": i3.AsyncPipe, "translate": i7.TranslatePipe, "assetPreview": AssetPreviewPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11601
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductVariantSelectorComponent, decorators: [{
11070
11602
  type: Component,
11071
- args: [{ selector: 'vdr-form-field', template: "<div\r\n class=\"form-group\"\r\n [class.no-label]=\"!label\"\r\n [class.clr-error]=\"formFieldControl?.formControlName?.invalid\"\r\n>\r\n <label *ngIf=\"label\" [for]=\"for\" class=\"clr-control-label\">\r\n {{ label }}\r\n <vdr-help-tooltip *ngIf=\"tooltip\" [content]=\"tooltip\"></vdr-help-tooltip>\r\n </label>\r\n <label\r\n [for]=\"for\"\r\n aria-haspopup=\"true\"\r\n role=\"tooltip\"\r\n [class.invalid]=\"formFieldControl?.touched && !formFieldControl?.valid\"\r\n class=\"tooltip tooltip-validation tooltip-sm tooltip-top-left\"\r\n >\r\n <div class=\"input-row\" [class.has-toggle]=\"readOnlyToggle\">\r\n <ng-content></ng-content>\r\n <button\r\n *ngIf=\"readOnlyToggle\"\r\n type=\"button\"\r\n [disabled]=\"!isReadOnly\"\r\n [title]=\"'common.edit-field' | translate\"\r\n class=\"btn btn-icon edit-button\"\r\n (click)=\"setReadOnly(false)\"\r\n >\r\n <clr-icon shape=\"edit\"></clr-icon>\r\n </button>\r\n </div>\r\n <div class=\"clr-subtext\" *ngIf=\"getErrorMessage()\">{{ getErrorMessage() }}</div>\r\n <span class=\"tooltip-content\">{{ label }} is required.</span>\r\n </label>\r\n</div>\r\n", styles: [":host{display:block}:host .form-group>label:first-child{top:6px}:host .form-group>label:nth-of-type(2){flex:1;max-width:20rem}:host .form-group>label:nth-of-type(2) ::ng-deep>*:not(.tooltip-content){width:100%}:host .form-group .tooltip-validation{height:initial}:host .form-group.no-label{margin:-6px 0 0;padding:0;justify-content:center}:host .form-group.no-label>label{position:relative;justify-content:center}:host .form-group.no-label .input-row{justify-content:center}:host .input-row{display:flex}:host .input-row ::ng-deep input{flex:1}:host .input-row ::ng-deep input[disabled]{background-color:var(--color-component-bg-200)}:host .input-row button.edit-button{margin:0;border-radius:0 3px 3px 0}:host .input-row.has-toggle ::ng-deep input{border-top-right-radius:0!important;border-bottom-right-radius:0!important;border-right:none}:host .input-row ::ng-deep clr-toggle-wrapper{margin-top:8px}.tooltip.tooltip-validation.invalid:before{position:absolute;content:\"\";height:.666667rem;width:.666667rem;top:.125rem;right:.25rem;background-image:url(data:image/svg+xml;charset=utf8,%3Csvg%20version%3D%221.1%22%20viewBox%3D%225%205%2026%2026%22%20preserveAspectRatio%3D%22xMidYMid%20meet%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%3Cdefs%3E%3Cstyle%3E.clr-i-outline%7Bfill%3A%23a32100%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctitle%3Eexclamation-circle-line%3C%2Ftitle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20class%3D%22clr-i-outline%20clr-i-outline-path-1%22%20d%3D%22M18%2C6A12%2C12%2C0%2C1%2C0%2C30%2C18%2C12%2C12%2C0%2C0%2C0%2C18%2C6Zm0%2C22A10%2C10%2C0%2C1%2C1%2C28%2C18%2C10%2C10%2C0%2C0%2C1%2C18%2C28Z%22%3E%3C%2Fpath%3E%3Cpath%20class%3D%22clr-i-outline%20clr-i-outline-path-2%22%20d%3D%22M18%2C20.07a1.3%2C1.3%2C0%2C0%2C1-1.3-1.3v-6a1.3%2C1.3%2C0%2C1%2C1%2C2.6%2C0v6A1.3%2C1.3%2C0%2C0%2C1%2C18%2C20.07Z%22%3E%3C%2Fpath%3E%3Ccircle%20class%3D%22clr-i-outline%20clr-i-outline-path-3%22%20cx%3D%2217.95%22%20cy%3D%2223.02%22%20r%3D%221.5%22%3E%3C%2Fcircle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fsvg%3E);background-repeat:no-repeat;background-size:contain;vertical-align:middle;margin:0}.tooltip.tooltip-sm>.tooltip-content,.tooltip .tooltip-content.tooltip-sm{width:5rem}.tooltip:hover>.tooltip-content{right:12px;margin-bottom:0}.tooltip:not(.invalid):hover>.tooltip-content{display:none}\n"] }]
11072
- }], propDecorators: { label: [{
11073
- type: Input
11074
- }], for: [{
11075
- type: Input
11076
- }], tooltip: [{
11077
- type: Input
11078
- }], errors: [{
11079
- type: Input
11080
- }], readOnlyToggle: [{
11081
- type: Input
11082
- }], formFieldControl: [{
11083
- type: ContentChild,
11084
- args: [FormFieldControlDirective, { static: true }]
11603
+ args: [{ selector: 'vdr-product-variant-selector', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-select\r\n #autoComplete\r\n [items]=\"searchResults$ | async\"\r\n [addTag]=\"false\"\r\n [multiple]=\"false\"\r\n [hideSelected]=\"true\"\r\n [loading]=\"searchLoading\"\r\n [typeahead]=\"searchInput$\"\r\n [appendTo]=\"'body'\"\r\n [placeholder]=\"'settings.search-by-product-name-or-sku' | translate\"\r\n (change)=\"selectResult($event)\"\r\n>\r\n <ng-template ng-option-tmp let-item=\"item\">\r\n <img [src]=\"item.productAsset | assetPreview: 32\">\r\n {{ item.productVariantName }}\r\n <small class=\"sku\">{{ item.sku }}</small>\r\n </ng-template>\r\n</ng-select>\r\n", styles: [":host{display:block}.sku{margin-left:12px;color:var(--color-grey-500)}\n"] }]
11604
+ }], ctorParameters: function () { return [{ type: DataService }]; }, propDecorators: { productSelected: [{
11605
+ type: Output
11606
+ }], ngSelect: [{
11607
+ type: ViewChild,
11608
+ args: ['autoComplete', { static: true }]
11085
11609
  }] } });
11086
11610
 
11087
11611
  /**
11088
- * ConfigArg values are always stored as strings. If they are not primitives, then
11089
- * they are JSON-encoded. This function unwraps them back into their original
11090
- * data type.
11612
+ * @description
11613
+ * Allows the selection of multiple ProductVariants via an autocomplete select input.
11614
+ * Should be used with `ID` type **list** fields which represent ProductVariant IDs.
11615
+ *
11616
+ * @docsCategory custom-input-components
11617
+ * @docsPage default-inputs
11091
11618
  */
11092
- function getConfigArgValue(value) {
11093
- try {
11094
- return value ? JSON.parse(value) : undefined;
11619
+ class ProductSelectorFormInputComponent {
11620
+ constructor(dataService) {
11621
+ this.dataService = dataService;
11622
+ this.isListInput = true;
11095
11623
  }
11096
- catch (e) {
11097
- return value;
11624
+ ngOnInit() {
11625
+ this.formControl.setValidators([
11626
+ control => {
11627
+ if (!control.value || !control.value.length) {
11628
+ return {
11629
+ atLeastOne: { length: control.value.length },
11630
+ };
11631
+ }
11632
+ return null;
11633
+ },
11634
+ ]);
11635
+ this.selection$ = this.formControl.valueChanges.pipe(startWith(this.formControl.value), switchMap(value => {
11636
+ if (Array.isArray(value) && 0 < value.length) {
11637
+ return forkJoin(value.map(id => this.dataService.product
11638
+ .getProductVariant(id)
11639
+ .mapSingle(data => data.productVariant)));
11640
+ }
11641
+ return of([]);
11642
+ }), map(variants => variants.filter(notNullOrUndefined)));
11643
+ }
11644
+ addProductVariant(product) {
11645
+ const value = this.formControl.value;
11646
+ this.formControl.setValue([...new Set([...value, product.productVariantId])]);
11647
+ }
11648
+ removeProductVariant(id) {
11649
+ const value = this.formControl.value;
11650
+ this.formControl.setValue(value.filter(_id => _id !== id));
11098
11651
  }
11099
11652
  }
11100
- function encodeConfigArgValue(value) {
11101
- return Array.isArray(value) ? JSON.stringify(value) : (value !== null && value !== void 0 ? value : '').toString();
11102
- }
11103
- /**
11104
- * Creates an empty ConfigurableOperation object based on the definition.
11105
- */
11106
- function configurableDefinitionToInstance(def) {
11107
- return Object.assign(Object.assign({}, def), { args: def.args.map(arg => {
11108
- return Object.assign(Object.assign({}, arg), { value: getDefaultConfigArgValue(arg) });
11109
- }) });
11110
- }
11653
+ ProductSelectorFormInputComponent.id = 'product-selector-form-input';
11654
+ ProductSelectorFormInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductSelectorFormInputComponent, deps: [{ token: DataService }], target: i0.ɵɵFactoryTarget.Component });
11655
+ ProductSelectorFormInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ProductSelectorFormInputComponent, selector: "vdr-product-selector-form-input", ngImport: i0, template: "<ul class=\"list-unstyled\">\r\n <li *ngFor=\"let variant of selection$ | async\" class=\"variant\">\r\n <div class=\"thumb\">\r\n <img [src]=\"variant.product.featuredAsset | assetPreview: 32\" />\r\n </div>\r\n <div class=\"detail\">\r\n <div>{{ variant.name }}</div>\r\n <div class=\"sku\">{{ variant.sku }}</div>\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <button\r\n class=\"btn btn-link btn-sm btn-warning\"\r\n (click)=\"removeProductVariant(variant.id)\"\r\n [title]=\"'common.remove-item-from-list' | translate\"\r\n >\r\n <clr-icon shape=\"times\"></clr-icon>\r\n </button>\r\n </li>\r\n</ul>\r\n<vdr-product-variant-selector (productSelected)=\"addProductVariant($event)\"></vdr-product-variant-selector>\r\n", styles: [".variant{margin-bottom:6px;display:flex;align-items:center;transition:background-color .2s}.variant:hover{background-color:var(--color-component-bg-200)}.thumb{margin-right:6px}.sku{color:var(--color-grey-400);font-size:smaller;line-height:1em}\n"], components: [{ type: ProductVariantSelectorComponent, selector: "vdr-product-variant-selector", outputs: ["productSelected"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }], pipes: { "async": i3.AsyncPipe, "assetPreview": AssetPreviewPipe, "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11656
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ProductSelectorFormInputComponent, decorators: [{
11657
+ type: Component,
11658
+ args: [{ selector: 'vdr-product-selector-form-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ul class=\"list-unstyled\">\r\n <li *ngFor=\"let variant of selection$ | async\" class=\"variant\">\r\n <div class=\"thumb\">\r\n <img [src]=\"variant.product.featuredAsset | assetPreview: 32\" />\r\n </div>\r\n <div class=\"detail\">\r\n <div>{{ variant.name }}</div>\r\n <div class=\"sku\">{{ variant.sku }}</div>\r\n </div>\r\n <div class=\"flex-spacer\"></div>\r\n <button\r\n class=\"btn btn-link btn-sm btn-warning\"\r\n (click)=\"removeProductVariant(variant.id)\"\r\n [title]=\"'common.remove-item-from-list' | translate\"\r\n >\r\n <clr-icon shape=\"times\"></clr-icon>\r\n </button>\r\n </li>\r\n</ul>\r\n<vdr-product-variant-selector (productSelected)=\"addProductVariant($event)\"></vdr-product-variant-selector>\r\n", styles: [".variant{margin-bottom:6px;display:flex;align-items:center;transition:background-color .2s}.variant:hover{background-color:var(--color-component-bg-200)}.thumb{margin-right:6px}.sku{color:var(--color-grey-400);font-size:smaller;line-height:1em}\n"] }]
11659
+ }], ctorParameters: function () { return [{ type: DataService }]; } });
11660
+
11111
11661
  /**
11112
- * Converts an object of the type:
11113
- * ```
11114
- * {
11115
- * code: 'my-operation',
11116
- * args: {
11117
- * someProperty: 'foo'
11118
- * }
11119
- * }
11120
- * ```
11121
- * to the format defined by the ConfigurableOperationInput GraphQL input type:
11122
- * ```
11123
- * {
11124
- * code: 'my-operation',
11125
- * args: [
11126
- * { name: 'someProperty', value: 'foo' }
11127
- * ]
11128
- * }
11129
- * ```
11662
+ * A component for selecting files to upload as new Assets.
11130
11663
  */
11131
- function toConfigurableOperationInput(operation, formValueOperations) {
11132
- return {
11133
- code: operation.code,
11134
- arguments: Object.values(formValueOperations.args || {}).map((value, j) => ({
11135
- name: operation.args[j].name,
11136
- value: value.hasOwnProperty('value')
11137
- ? encodeConfigArgValue(value.value)
11138
- : encodeConfigArgValue(value),
11139
- })),
11140
- };
11141
- }
11142
- function configurableOperationValueIsValid(def, value) {
11143
- if (!def || !value) {
11144
- return false;
11664
+ class AssetFileInputComponent {
11665
+ constructor(serverConfig) {
11666
+ this.serverConfig = serverConfig;
11667
+ /**
11668
+ * CSS selector of the DOM element which will be masked by the file
11669
+ * drop zone. Defaults to `body`.
11670
+ */
11671
+ this.dropZoneTarget = 'body';
11672
+ this.uploading = false;
11673
+ this.selectFiles = new EventEmitter();
11674
+ this.dragging = false;
11675
+ this.overDropZone = false;
11676
+ this.dropZoneStyle = {
11677
+ 'width.px': 0,
11678
+ 'height.px': 0,
11679
+ 'top.px': 0,
11680
+ 'left.px': 0,
11681
+ };
11145
11682
  }
11146
- if (def.code !== value.code) {
11147
- return false;
11683
+ ngOnInit() {
11684
+ this.accept = this.serverConfig.serverConfig.permittedAssetTypes.join(',');
11685
+ this.fitDropZoneToTarget();
11148
11686
  }
11149
- for (const argDef of def.args) {
11150
- const argVal = value.args[argDef.name];
11151
- if (argDef.required && (argVal == null || argVal === '' || argVal === '0')) {
11152
- return false;
11687
+ onDragEnter() {
11688
+ this.dragging = true;
11689
+ this.fitDropZoneToTarget();
11690
+ }
11691
+ // DragEvent is not supported in Safari, see https://github.com/vendure-ecommerce/vendure/pull/284
11692
+ onDragLeave(event) {
11693
+ if (!event.clientX && !event.clientY) {
11694
+ this.dragging = false;
11153
11695
  }
11154
11696
  }
11155
- return true;
11156
- }
11157
- /**
11158
- * Returns a default value based on the type of the config arg.
11159
- */
11160
- function getDefaultConfigArgValue(arg) {
11161
- if (arg.list) {
11162
- return [];
11697
+ /**
11698
+ * Preventing this event is required to make dropping work.
11699
+ * See https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API#Define_a_drop_zone
11700
+ */
11701
+ onDragOver(event) {
11702
+ event.preventDefault();
11163
11703
  }
11164
- if (arg.defaultValue) {
11165
- return arg.defaultValue;
11704
+ // DragEvent is not supported in Safari, see https://github.com/vendure-ecommerce/vendure/pull/284
11705
+ onDrop(event) {
11706
+ event.preventDefault();
11707
+ this.dragging = false;
11708
+ this.overDropZone = false;
11709
+ const files = Array.from(event.dataTransfer ? event.dataTransfer.items : [])
11710
+ .map(i => i.getAsFile())
11711
+ .filter(notNullOrUndefined);
11712
+ this.selectFiles.emit(files);
11166
11713
  }
11167
- const type = arg.type;
11168
- switch (type) {
11169
- case 'string':
11170
- case 'datetime':
11171
- case 'float':
11172
- case 'ID':
11173
- case 'int':
11174
- return null;
11175
- case 'boolean':
11176
- return false;
11177
- default:
11178
- assertNever(type);
11714
+ select(event) {
11715
+ const files = event.target.files;
11716
+ if (files) {
11717
+ this.selectFiles.emit(Array.from(files));
11718
+ }
11179
11719
  }
11180
- }
11720
+ fitDropZoneToTarget() {
11721
+ const target = document.querySelector(this.dropZoneTarget);
11722
+ if (target) {
11723
+ const rect = target.getBoundingClientRect();
11724
+ this.dropZoneStyle['width.px'] = rect.width;
11725
+ this.dropZoneStyle['height.px'] = rect.height;
11726
+ this.dropZoneStyle['top.px'] = rect.top;
11727
+ this.dropZoneStyle['left.px'] = rect.left;
11728
+ }
11729
+ }
11730
+ }
11731
+ AssetFileInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetFileInputComponent, deps: [{ token: ServerConfigService }], target: i0.ɵɵFactoryTarget.Component });
11732
+ AssetFileInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: AssetFileInputComponent, selector: "vdr-asset-file-input", inputs: { dropZoneTarget: "dropZoneTarget", uploading: "uploading" }, outputs: { selectFiles: "selectFiles" }, host: { listeners: { "document:dragenter": "onDragEnter()", "document:dragleave": "onDragLeave($event)" } }, ngImport: i0, template: "<input type=\"file\" class=\"file-input\" #fileInput (change)=\"select($event)\" multiple [accept]=\"accept\" />\r\n<button class=\"btn btn-primary\" (click)=\"fileInput.click()\" [disabled]=\"uploading\">\r\n <ng-container *ngIf=\"uploading; else selectable\">\r\n <clr-spinner clrInline></clr-spinner>\r\n {{ 'asset.uploading' | translate }}\r\n </ng-container>\r\n <ng-template #selectable>\r\n <clr-icon shape=\"upload-cloud\"></clr-icon>\r\n {{ 'asset.upload-assets' | translate }}\r\n </ng-template>\r\n</button>\r\n<div\r\n class=\"drop-zone\"\r\n [ngStyle]=\"dropZoneStyle\"\r\n [class.visible]=\"dragging\"\r\n [class.dragging-over]=\"overDropZone\"\r\n (dragenter)=\"overDropZone = true\"\r\n (dragleave)=\"overDropZone = false\"\r\n (dragover)=\"onDragOver($event)\"\r\n (drop)=\"onDrop($event)\"\r\n #dropZone\r\n>\r\n <div class=\"drop-label\" (dragenter)=\"overDropZone = true\">\r\n <clr-icon shape=\"upload-cloud\" size=\"32\"></clr-icon>\r\n {{ 'catalog.drop-files-to-upload' | translate }}\r\n </div>\r\n</div>\r\n", styles: [".file-input{display:none}.drop-zone{position:fixed;background-color:var(--color-primary-500);border:3px dashed var(--color-component-border-300);opacity:0;visibility:hidden;z-index:1000;transition:opacity .2s,background-color .2s,visibility 0s .2s;display:flex;align-items:center;justify-content:center}.drop-zone.visible{opacity:.3;visibility:visible;transition:opacity .2s,background-color .2s,border .2s,visibility 0s}.drop-zone .drop-label{background-color:#fffc;border-radius:3px;padding:24px;font-size:32px;pointer-events:none;opacity:.5;transition:opacity .2s}.drop-zone.dragging-over{border-color:#fff;background-color:var(--color-primary-500);opacity:.7;transition:background-color .2s,border .2s}.drop-zone.dragging-over .drop-label{opacity:1}\n"], components: [{ type: i1$3.ClrSpinner, selector: "clr-spinner", inputs: ["clrInline", "clrInverse", "clrSmall", "clrMedium"] }], directives: [{ type: FormFieldControlDirective, selector: "input, textarea, select" }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], pipes: { "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11733
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetFileInputComponent, decorators: [{
11734
+ type: Component,
11735
+ args: [{ selector: 'vdr-asset-file-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<input type=\"file\" class=\"file-input\" #fileInput (change)=\"select($event)\" multiple [accept]=\"accept\" />\r\n<button class=\"btn btn-primary\" (click)=\"fileInput.click()\" [disabled]=\"uploading\">\r\n <ng-container *ngIf=\"uploading; else selectable\">\r\n <clr-spinner clrInline></clr-spinner>\r\n {{ 'asset.uploading' | translate }}\r\n </ng-container>\r\n <ng-template #selectable>\r\n <clr-icon shape=\"upload-cloud\"></clr-icon>\r\n {{ 'asset.upload-assets' | translate }}\r\n </ng-template>\r\n</button>\r\n<div\r\n class=\"drop-zone\"\r\n [ngStyle]=\"dropZoneStyle\"\r\n [class.visible]=\"dragging\"\r\n [class.dragging-over]=\"overDropZone\"\r\n (dragenter)=\"overDropZone = true\"\r\n (dragleave)=\"overDropZone = false\"\r\n (dragover)=\"onDragOver($event)\"\r\n (drop)=\"onDrop($event)\"\r\n #dropZone\r\n>\r\n <div class=\"drop-label\" (dragenter)=\"overDropZone = true\">\r\n <clr-icon shape=\"upload-cloud\" size=\"32\"></clr-icon>\r\n {{ 'catalog.drop-files-to-upload' | translate }}\r\n </div>\r\n</div>\r\n", styles: [".file-input{display:none}.drop-zone{position:fixed;background-color:var(--color-primary-500);border:3px dashed var(--color-component-border-300);opacity:0;visibility:hidden;z-index:1000;transition:opacity .2s,background-color .2s,visibility 0s .2s;display:flex;align-items:center;justify-content:center}.drop-zone.visible{opacity:.3;visibility:visible;transition:opacity .2s,background-color .2s,border .2s,visibility 0s}.drop-zone .drop-label{background-color:#fffc;border-radius:3px;padding:24px;font-size:32px;pointer-events:none;opacity:.5;transition:opacity .2s}.drop-zone.dragging-over{border-color:#fff;background-color:var(--color-primary-500);opacity:.7;transition:background-color .2s,border .2s}.drop-zone.dragging-over .drop-label{opacity:1}\n"] }]
11736
+ }], ctorParameters: function () { return [{ type: ServerConfigService }]; }, propDecorators: { dropZoneTarget: [{
11737
+ type: Input
11738
+ }], uploading: [{
11739
+ type: Input
11740
+ }], selectFiles: [{
11741
+ type: Output
11742
+ }], onDragEnter: [{
11743
+ type: HostListener,
11744
+ args: ['document:dragenter']
11745
+ }], onDragLeave: [{
11746
+ type: HostListener,
11747
+ args: ['document:dragleave', ['$event']]
11748
+ }] } });
11181
11749
 
11182
- /**
11183
- * A host component which delegates to an instance or list of FormInputComponent components.
11184
- */
11185
- class DynamicFormInputComponent {
11186
- constructor(componentRegistryService, componentFactoryResolver, changeDetectorRef, injector) {
11187
- this.componentRegistryService = componentRegistryService;
11188
- this.componentFactoryResolver = componentFactoryResolver;
11189
- this.changeDetectorRef = changeDetectorRef;
11190
- this.injector = injector;
11191
- this.renderAsList = false;
11192
- this.listItems = [];
11193
- this.listId = 1;
11194
- this.listFormArray = new FormArray([]);
11195
- this.renderList$ = new Subject();
11196
- this.destroy$ = new Subject();
11750
+ class AssetSearchInputComponent {
11751
+ constructor() {
11752
+ this.searchTermChange = new EventEmitter();
11753
+ this.tagsChange = new EventEmitter();
11754
+ this.lastTerm = '';
11755
+ this.lastTagIds = [];
11756
+ this.filterTagResults = (term, item) => {
11757
+ if (!this.isTag(item)) {
11758
+ return false;
11759
+ }
11760
+ return item.value.toLowerCase().startsWith(term.toLowerCase());
11761
+ };
11762
+ this.isTag = (input) => {
11763
+ return typeof input === 'object' && !!input && input.hasOwnProperty('value');
11764
+ };
11197
11765
  }
11198
- ngOnInit() {
11199
- const componentId = this.getInputComponentConfig(this.def).component;
11200
- const componentType = this.componentRegistryService.getInputComponent(componentId);
11201
- if (componentType) {
11202
- this.componentType = componentType;
11766
+ setSearchTerm(term) {
11767
+ if (term) {
11768
+ this.selectComponent.select({ label: term, value: { label: term } });
11203
11769
  }
11204
11770
  else {
11205
- // tslint:disable-next-line:no-console
11206
- console.error(`No form input component registered with the id "${componentId}". Using the default input instead.`);
11207
- const defaultComponentType = this.componentRegistryService.getInputComponent(this.getInputComponentConfig(Object.assign(Object.assign({}, this.def), { ui: undefined })).component);
11208
- if (defaultComponentType) {
11209
- this.componentType = defaultComponentType;
11771
+ const currentTerm = this.selectComponent.selectedItems.find(i => !this.isTag(i.value));
11772
+ if (currentTerm) {
11773
+ this.selectComponent.unselect(currentTerm);
11210
11774
  }
11211
11775
  }
11212
11776
  }
11213
- ngAfterViewInit() {
11214
- var _a;
11215
- if (this.componentType) {
11216
- const factory = this.componentFactoryResolver.resolveComponentFactory(this.componentType);
11217
- // create a temp instance to check the value of `isListInput`
11218
- const cmpRef = factory.create(this.injector);
11219
- const isListInputComponent = (_a = cmpRef.instance.isListInput) !== null && _a !== void 0 ? _a : false;
11220
- cmpRef.destroy();
11221
- if (this.def.list === false && isListInputComponent) {
11222
- throw new Error(`The ${this.componentType.name} component is a list input, but the definition for ${this.def.name} does not expect a list`);
11223
- }
11224
- this.renderAsList = this.def.list && !isListInputComponent;
11225
- if (!this.renderAsList) {
11226
- this.singleComponentRef = this.renderInputComponent(factory, this.singleViewContainer, this.control);
11777
+ setTags(tags) {
11778
+ const items = this.selectComponent.items;
11779
+ this.selectComponent.selectedItems.forEach(item => {
11780
+ if (this.isTag(item.value) && !tags.map(t => t.id).includes(item.id)) {
11781
+ this.selectComponent.unselect(item);
11227
11782
  }
11228
- else {
11229
- let formArraySub;
11230
- const renderListInputs = (viewContainerRefs) => {
11231
- if (viewContainerRefs.length) {
11232
- if (formArraySub) {
11233
- formArraySub.unsubscribe();
11234
- }
11235
- this.listFormArray = new FormArray([]);
11236
- this.listItems.forEach(i => { var _a; return (_a = i.componentRef) === null || _a === void 0 ? void 0 : _a.destroy(); });
11237
- viewContainerRefs.forEach((ref, i) => {
11238
- var _a;
11239
- const listItem = (_a = this.listItems) === null || _a === void 0 ? void 0 : _a[i];
11240
- if (listItem) {
11241
- this.listFormArray.push(listItem.control);
11242
- listItem.componentRef = this.renderInputComponent(factory, ref, listItem.control);
11243
- }
11244
- });
11245
- formArraySub = this.listFormArray.valueChanges
11246
- .pipe(takeUntil(this.destroy$))
11247
- .subscribe(val => {
11248
- this.control.markAsTouched();
11249
- this.control.markAsDirty();
11250
- this.onChange(val);
11251
- this.control.patchValue(val, { emitEvent: false });
11252
- });
11253
- setTimeout(() => this.changeDetectorRef.markForCheck());
11254
- }
11255
- };
11256
- // initial render
11257
- this.listItemContainers.changes
11258
- .pipe(take(1))
11259
- .subscribe(val => renderListInputs(this.listItemContainers));
11260
- // render on changes to the list
11261
- this.renderList$
11262
- .pipe(switchMap(() => this.listItemContainers.changes.pipe(take(1))), takeUntil(this.destroy$))
11263
- .subscribe(() => {
11264
- renderListInputs(this.listItemContainers);
11265
- });
11783
+ });
11784
+ tags.map(tag => {
11785
+ return items === null || items === void 0 ? void 0 : items.find(item => this.isTag(item) && item.id === tag.id);
11786
+ })
11787
+ .filter(notNullOrUndefined)
11788
+ .forEach(item => {
11789
+ const isSelected = this.selectComponent.selectedItems.find(i => {
11790
+ const val = i.value;
11791
+ if (this.isTag(val)) {
11792
+ return val.id === item.id;
11793
+ }
11794
+ return false;
11795
+ });
11796
+ if (!isSelected) {
11797
+ this.selectComponent.select({ label: '', value: item });
11266
11798
  }
11267
- }
11268
- setTimeout(() => this.changeDetectorRef.markForCheck());
11799
+ });
11269
11800
  }
11270
- ngOnChanges(changes) {
11271
- if (this.listItems) {
11272
- for (const item of this.listItems) {
11273
- if (item.componentRef) {
11274
- this.updateBindings(changes, item.componentRef);
11275
- }
11801
+ onSelectChange(selectedItems) {
11802
+ if (!Array.isArray(selectedItems)) {
11803
+ selectedItems = [selectedItems];
11804
+ }
11805
+ const searchTermItems = selectedItems.filter(item => !this.isTag(item));
11806
+ if (1 < searchTermItems.length) {
11807
+ for (let i = 0; i < searchTermItems.length - 1; i++) {
11808
+ // this.selectComponent.unselect(searchTermItems[i] as any);
11276
11809
  }
11277
11810
  }
11278
- if (this.singleComponentRef) {
11279
- this.updateBindings(changes, this.singleComponentRef);
11811
+ const searchTermItem = searchTermItems[searchTermItems.length - 1];
11812
+ const searchTerm = searchTermItem ? searchTermItem.label : '';
11813
+ const tags = selectedItems.filter(this.isTag);
11814
+ if (searchTerm !== this.lastTerm) {
11815
+ this.searchTermChange.emit(searchTerm);
11816
+ this.lastTerm = searchTerm;
11817
+ }
11818
+ if (this.lastTagIds.join(',') !== tags.map(t => t.id).join(',')) {
11819
+ this.tagsChange.emit(tags);
11820
+ this.lastTagIds = tags.map(t => t.id);
11280
11821
  }
11281
11822
  }
11282
- ngOnDestroy() {
11283
- this.destroy$.next();
11284
- this.destroy$.complete();
11823
+ isSearchHeaderSelected() {
11824
+ return this.selectComponent.itemsList.markedIndex === -1;
11285
11825
  }
11286
- updateBindings(changes, componentRef) {
11287
- if ('def' in changes) {
11288
- componentRef.instance.config = simpleDeepClone(this.def);
11826
+ addTagFn(item) {
11827
+ return { label: item };
11828
+ }
11829
+ }
11830
+ AssetSearchInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetSearchInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11831
+ AssetSearchInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: AssetSearchInputComponent, selector: "vdr-asset-search-input", inputs: { tags: "tags" }, outputs: { searchTermChange: "searchTermChange", tagsChange: "tagsChange" }, providers: [{ provide: SELECTION_MODEL_FACTORY, useValue: SingleSearchSelectionModelFactory }], viewQueries: [{ propertyName: "selectComponent", first: true, predicate: ["selectComponent"], descendants: true, static: true }], ngImport: i0, template: "<ng-select\r\n [addTag]=\"addTagFn\"\r\n [placeholder]=\"'catalog.search-asset-name-or-tag' | translate\"\r\n [items]=\"tags\"\r\n [searchFn]=\"filterTagResults\"\r\n [hideSelected]=\"true\"\r\n [multiple]=\"true\"\r\n [markFirst]=\"false\"\r\n (change)=\"onSelectChange($event)\"\r\n #selectComponent\r\n>\r\n <ng-template ng-header-tmp>\r\n <div\r\n class=\"search-header\"\r\n *ngIf=\"selectComponent.searchTerm\"\r\n [class.selected]=\"isSearchHeaderSelected()\"\r\n (click)=\"selectComponent.selectTag()\"\r\n >\r\n {{ 'catalog.search-for-term' | translate }}: {{ selectComponent.searchTerm }}\r\n </div>\r\n </ng-template>\r\n <ng-template ng-label-tmp let-item=\"item\" let-clear=\"clear\">\r\n <ng-container *ngIf=\"item.value\">\r\n <vdr-chip [colorFrom]=\"item.value\" icon=\"close\" (iconClick)=\"clear(item)\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ item.value }}</vdr-chip>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.value\">\r\n <vdr-chip [icon]=\"'times'\" (iconClick)=\"clear(item)\">\"{{ item.label || item }}\"</vdr-chip>\r\n </ng-container>\r\n </ng-template>\r\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\r\n <ng-container *ngIf=\"item.value\">\r\n <vdr-chip [colorFrom]=\"item.value\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ item.value }}</vdr-chip>\r\n </ng-container>\r\n </ng-template>\r\n</ng-select>\r\n", styles: [":host{display:block;width:100%}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background:none;margin:0}:host ::ng-deep .ng-dropdown-panel-items div.ng-option:last-child{display:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border:none;padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-left:8px}ng-select{width:100%;min-width:300px;margin-right:12px}.search-header{padding:8px 10px;border-bottom:1px solid var(--color-component-border-100);cursor:pointer}.search-header.selected,.search-header:hover{background-color:var(--color-component-bg-200)}\n"], components: [{ type: i2$1.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { type: ChipComponent, selector: "vdr-chip", inputs: ["icon", "invert", "colorFrom", "colorType"], outputs: ["iconClick"] }], directives: [{ type: i2$1.NgHeaderTemplateDirective, selector: "[ng-header-tmp]" }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2$1.NgLabelTemplateDirective, selector: "[ng-label-tmp]" }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i2$1.NgOptionTemplateDirective, selector: "[ng-option-tmp]" }], pipes: { "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11832
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetSearchInputComponent, decorators: [{
11833
+ type: Component,
11834
+ args: [{ selector: 'vdr-asset-search-input', changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: SELECTION_MODEL_FACTORY, useValue: SingleSearchSelectionModelFactory }], template: "<ng-select\r\n [addTag]=\"addTagFn\"\r\n [placeholder]=\"'catalog.search-asset-name-or-tag' | translate\"\r\n [items]=\"tags\"\r\n [searchFn]=\"filterTagResults\"\r\n [hideSelected]=\"true\"\r\n [multiple]=\"true\"\r\n [markFirst]=\"false\"\r\n (change)=\"onSelectChange($event)\"\r\n #selectComponent\r\n>\r\n <ng-template ng-header-tmp>\r\n <div\r\n class=\"search-header\"\r\n *ngIf=\"selectComponent.searchTerm\"\r\n [class.selected]=\"isSearchHeaderSelected()\"\r\n (click)=\"selectComponent.selectTag()\"\r\n >\r\n {{ 'catalog.search-for-term' | translate }}: {{ selectComponent.searchTerm }}\r\n </div>\r\n </ng-template>\r\n <ng-template ng-label-tmp let-item=\"item\" let-clear=\"clear\">\r\n <ng-container *ngIf=\"item.value\">\r\n <vdr-chip [colorFrom]=\"item.value\" icon=\"close\" (iconClick)=\"clear(item)\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ item.value }}</vdr-chip>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.value\">\r\n <vdr-chip [icon]=\"'times'\" (iconClick)=\"clear(item)\">\"{{ item.label || item }}\"</vdr-chip>\r\n </ng-container>\r\n </ng-template>\r\n <ng-template ng-option-tmp let-item=\"item\" let-index=\"index\" let-search=\"searchTerm\">\r\n <ng-container *ngIf=\"item.value\">\r\n <vdr-chip [colorFrom]=\"item.value\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ item.value }}</vdr-chip>\r\n </ng-container>\r\n </ng-template>\r\n</ng-select>\r\n", styles: [":host{display:block;width:100%}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background:none;margin:0}:host ::ng-deep .ng-dropdown-panel-items div.ng-option:last-child{display:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border:none;padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-left:8px}ng-select{width:100%;min-width:300px;margin-right:12px}.search-header{padding:8px 10px;border-bottom:1px solid var(--color-component-border-100);cursor:pointer}.search-header.selected,.search-header:hover{background-color:var(--color-component-bg-200)}\n"] }]
11835
+ }], propDecorators: { tags: [{
11836
+ type: Input
11837
+ }], searchTermChange: [{
11838
+ type: Output
11839
+ }], tagsChange: [{
11840
+ type: Output
11841
+ }], selectComponent: [{
11842
+ type: ViewChild,
11843
+ args: ['selectComponent', { static: true }]
11844
+ }] } });
11845
+
11846
+ class ManageTagsDialogComponent {
11847
+ constructor(dataService) {
11848
+ this.dataService = dataService;
11849
+ this.toDelete = [];
11850
+ this.toUpdate = [];
11851
+ }
11852
+ ngOnInit() {
11853
+ this.allTags$ = this.dataService.product.getTagList().mapStream(data => data.tags.items);
11854
+ }
11855
+ toggleDelete(id) {
11856
+ const marked = this.markedAsDeleted(id);
11857
+ if (marked) {
11858
+ this.toDelete = this.toDelete.filter(_id => _id !== id);
11289
11859
  }
11290
- if ('readonly' in changes) {
11291
- componentRef.instance.readonly = this.readonly;
11860
+ else {
11861
+ this.toDelete.push(id);
11292
11862
  }
11293
- componentRef.injector.get(ChangeDetectorRef).markForCheck();
11294
11863
  }
11295
- trackById(index, item) {
11296
- return item.id;
11864
+ markedAsDeleted(id) {
11865
+ return this.toDelete.includes(id);
11297
11866
  }
11298
- addListItem() {
11299
- var _a;
11300
- if (!this.listItems) {
11301
- this.listItems = [];
11867
+ updateTagValue(id, value) {
11868
+ const exists = this.toUpdate.find(i => i.id === id);
11869
+ if (exists) {
11870
+ exists.value = value;
11871
+ }
11872
+ else {
11873
+ this.toUpdate.push({ id, value });
11302
11874
  }
11303
- this.listItems.push({
11304
- id: this.listId++,
11305
- control: new FormControl((_a = this.def.defaultValue) !== null && _a !== void 0 ? _a : null),
11306
- });
11307
- this.renderList$.next();
11308
11875
  }
11309
- moveListItem(event) {
11310
- if (this.listItems) {
11311
- moveItemInArray(this.listItems, event.previousIndex, event.currentIndex);
11312
- this.listFormArray.removeAt(event.previousIndex);
11313
- this.listFormArray.insert(event.currentIndex, event.item.data.control);
11314
- this.renderList$.next();
11876
+ saveChanges() {
11877
+ const operations = [];
11878
+ for (const id of this.toDelete) {
11879
+ operations.push(this.dataService.product.deleteTag(id));
11880
+ }
11881
+ for (const item of this.toUpdate) {
11882
+ if (!this.toDelete.includes(item.id)) {
11883
+ operations.push(this.dataService.product.updateTag(item));
11884
+ }
11315
11885
  }
11886
+ return forkJoin(operations).subscribe(() => this.resolveWith(true));
11887
+ }
11888
+ }
11889
+ ManageTagsDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ManageTagsDialogComponent, deps: [{ token: DataService }], target: i0.ɵɵFactoryTarget.Component });
11890
+ ManageTagsDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ManageTagsDialogComponent, selector: "vdr-manage-tags-dialog", ngImport: i0, template: "<ng-template vdrDialogTitle>\r\n <span>{{ 'common.manage-tags' | translate }}</span>\r\n</ng-template>\r\n<p class=\"mt0 mb4\">{{ 'common.manage-tags-description' | translate }}</p>\r\n<ul class=\"tag-list\" *ngFor=\"let tag of allTags$ | async\">\r\n <li class=\"mb2 p1\" [class.to-delete]=\"markedAsDeleted(tag.id)\">\r\n <clr-icon shape=\"tag\" class=\"is-solid mr2\" [style.color]=\"tag.value | stringToColor\"></clr-icon>\r\n <input type=\"text\" (input)=\"updateTagValue(tag.id, $event.target.value)\" [value]=\"tag.value\" />\r\n <button class=\"icon-button\" (click)=\"toggleDelete(tag.id)\">\r\n <clr-icon shape=\"trash\" class=\"is-danger\" [class.is-solid]=\"markedAsDeleted(tag.id)\"></clr-icon>\r\n </button>\r\n </li>\r\n</ul>\r\n<ng-template vdrDialogButtons>\r\n <button type=\"submit\" (click)=\"resolveWith(false)\" class=\"btn btn-secondary\">\r\n {{ 'common.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"submit\"\r\n (click)=\"saveChanges()\"\r\n class=\"btn btn-primary\"\r\n [disabled]=\"!toUpdate.length && !toDelete.length\"\r\n >\r\n {{ 'common.update' | translate }}\r\n </button>\r\n</ng-template>\r\n", styles: [".tag-list{list-style-type:none}.tag-list li{display:flex;align-items:center}.tag-list li input{max-width:170px}.tag-list li.to-delete{opacity:.7;background-color:var(--color-component-bg-300)}.tag-list li.to-delete input{background-color:transparent!important}\n"], directives: [{ type: DialogTitleDirective, selector: "[vdrDialogTitle]" }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: FormFieldControlDirective, selector: "input, textarea, select" }, { type: DialogButtonsDirective, selector: "[vdrDialogButtons]" }], pipes: { "translate": i7.TranslatePipe, "async": i3.AsyncPipe, "stringToColor": StringToColorPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11891
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ManageTagsDialogComponent, decorators: [{
11892
+ type: Component,
11893
+ args: [{ selector: 'vdr-manage-tags-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template vdrDialogTitle>\r\n <span>{{ 'common.manage-tags' | translate }}</span>\r\n</ng-template>\r\n<p class=\"mt0 mb4\">{{ 'common.manage-tags-description' | translate }}</p>\r\n<ul class=\"tag-list\" *ngFor=\"let tag of allTags$ | async\">\r\n <li class=\"mb2 p1\" [class.to-delete]=\"markedAsDeleted(tag.id)\">\r\n <clr-icon shape=\"tag\" class=\"is-solid mr2\" [style.color]=\"tag.value | stringToColor\"></clr-icon>\r\n <input type=\"text\" (input)=\"updateTagValue(tag.id, $event.target.value)\" [value]=\"tag.value\" />\r\n <button class=\"icon-button\" (click)=\"toggleDelete(tag.id)\">\r\n <clr-icon shape=\"trash\" class=\"is-danger\" [class.is-solid]=\"markedAsDeleted(tag.id)\"></clr-icon>\r\n </button>\r\n </li>\r\n</ul>\r\n<ng-template vdrDialogButtons>\r\n <button type=\"submit\" (click)=\"resolveWith(false)\" class=\"btn btn-secondary\">\r\n {{ 'common.cancel' | translate }}\r\n </button>\r\n <button\r\n type=\"submit\"\r\n (click)=\"saveChanges()\"\r\n class=\"btn btn-primary\"\r\n [disabled]=\"!toUpdate.length && !toDelete.length\"\r\n >\r\n {{ 'common.update' | translate }}\r\n </button>\r\n</ng-template>\r\n", styles: [".tag-list{list-style-type:none}.tag-list li{display:flex;align-items:center}.tag-list li input{max-width:170px}.tag-list li.to-delete{opacity:.7;background-color:var(--color-component-bg-300)}.tag-list li.to-delete input{background-color:transparent!important}\n"] }]
11894
+ }], ctorParameters: function () { return [{ type: DataService }]; } });
11895
+
11896
+ class FocalPointControlComponent {
11897
+ constructor() {
11898
+ this.visible = false;
11899
+ this.editable = false;
11900
+ this.fpx = 0.5;
11901
+ this.fpy = 0.5;
11902
+ this.focalPointChange = new EventEmitter();
11903
+ }
11904
+ get initialPosition() {
11905
+ return this.focalPointToOffset(this.fpx == null ? 0.5 : this.fpx, this.fpy == null ? 0.5 : this.fpy);
11906
+ }
11907
+ onDragEnded(event) {
11908
+ const { x, y } = this.getCurrentFocalPoint();
11909
+ this.fpx = x;
11910
+ this.fpy = y;
11911
+ this.focalPointChange.emit({ x, y });
11912
+ }
11913
+ getCurrentFocalPoint() {
11914
+ const { left: dotLeft, top: dotTop, width, height } = this.dot.nativeElement.getBoundingClientRect();
11915
+ const { left: frameLeft, top: frameTop } = this.frame.nativeElement.getBoundingClientRect();
11916
+ const xInPx = dotLeft - frameLeft + width / 2;
11917
+ const yInPx = dotTop - frameTop + height / 2;
11918
+ return {
11919
+ x: xInPx / this.width,
11920
+ y: yInPx / this.height,
11921
+ };
11922
+ }
11923
+ focalPointToOffset(x, y) {
11924
+ const { width, height } = this.dot.nativeElement.getBoundingClientRect();
11925
+ return {
11926
+ x: x * this.width - width / 2,
11927
+ y: y * this.height - height / 2,
11928
+ };
11929
+ }
11930
+ }
11931
+ FocalPointControlComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: FocalPointControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
11932
+ FocalPointControlComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: FocalPointControlComponent, selector: "vdr-focal-point-control", inputs: { visible: "visible", editable: "editable", width: "width", height: "height", fpx: "fpx", fpy: "fpy" }, outputs: { focalPointChange: "focalPointChange" }, host: { properties: { "style.width.px": "this.width", "style.height.px": "this.height" } }, viewQueries: [{ propertyName: "frame", first: true, predicate: ["frame"], descendants: true, static: true }, { propertyName: "dot", first: true, predicate: ["dot"], descendants: true, static: true }], ngImport: i0, template: "<ng-content></ng-content>\r\n<div class=\"frame\" #frame [style.width.px]=\"width\" [style.height.px]=\"height\">\r\n <div\r\n #dot\r\n class=\"dot\"\r\n [class.visible]=\"visible\"\r\n [class.editable]=\"editable\"\r\n cdkDrag\r\n [cdkDragDisabled]=\"!editable\"\r\n cdkDragBoundary=\".frame\"\r\n (cdkDragEnded)=\"onDragEnded($event)\"\r\n [cdkDragFreeDragPosition]=\"initialPosition\"\r\n ></div>\r\n</div>\r\n", styles: [":host{position:relative;display:block}.frame{position:absolute;top:0}.dot{width:20px;height:20px;border-radius:50%;border:2px solid white;position:absolute;visibility:hidden;transition:opacity .3s;box-shadow:0 0 4px 4px #0000006b}.dot.visible{visibility:visible;opacity:.7}.dot.editable{cursor:move;visibility:visible;opacity:1;animation:pulse;animation-duration:.5s;animation-iteration-count:4}@keyframes pulse{0%{border-color:#fff}50%{border-color:var(--color-warning-500)}to{border-color:#fff}}\n"], directives: [{ type: i3$1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11933
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: FocalPointControlComponent, decorators: [{
11934
+ type: Component,
11935
+ args: [{ selector: 'vdr-focal-point-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content></ng-content>\r\n<div class=\"frame\" #frame [style.width.px]=\"width\" [style.height.px]=\"height\">\r\n <div\r\n #dot\r\n class=\"dot\"\r\n [class.visible]=\"visible\"\r\n [class.editable]=\"editable\"\r\n cdkDrag\r\n [cdkDragDisabled]=\"!editable\"\r\n cdkDragBoundary=\".frame\"\r\n (cdkDragEnded)=\"onDragEnded($event)\"\r\n [cdkDragFreeDragPosition]=\"initialPosition\"\r\n ></div>\r\n</div>\r\n", styles: [":host{position:relative;display:block}.frame{position:absolute;top:0}.dot{width:20px;height:20px;border-radius:50%;border:2px solid white;position:absolute;visibility:hidden;transition:opacity .3s;box-shadow:0 0 4px 4px #0000006b}.dot.visible{visibility:visible;opacity:.7}.dot.editable{cursor:move;visibility:visible;opacity:1;animation:pulse;animation-duration:.5s;animation-iteration-count:4}@keyframes pulse{0%{border-color:#fff}50%{border-color:var(--color-warning-500)}to{border-color:#fff}}\n"] }]
11936
+ }], propDecorators: { visible: [{
11937
+ type: Input
11938
+ }], editable: [{
11939
+ type: Input
11940
+ }], width: [{
11941
+ type: HostBinding,
11942
+ args: ['style.width.px']
11943
+ }, {
11944
+ type: Input
11945
+ }], height: [{
11946
+ type: HostBinding,
11947
+ args: ['style.height.px']
11948
+ }, {
11949
+ type: Input
11950
+ }], fpx: [{
11951
+ type: Input
11952
+ }], fpy: [{
11953
+ type: Input
11954
+ }], focalPointChange: [{
11955
+ type: Output
11956
+ }], frame: [{
11957
+ type: ViewChild,
11958
+ args: ['frame', { static: true }]
11959
+ }], dot: [{
11960
+ type: ViewChild,
11961
+ args: ['dot', { static: true }]
11962
+ }] } });
11963
+
11964
+ class TagSelectorComponent {
11965
+ constructor(dataService) {
11966
+ this.dataService = dataService;
11316
11967
  }
11317
- removeListItem(item) {
11318
- var _a;
11319
- if (this.listItems) {
11320
- const index = this.listItems.findIndex(i => i === item);
11321
- (_a = item.componentRef) === null || _a === void 0 ? void 0 : _a.destroy();
11322
- this.listFormArray.removeAt(index);
11323
- this.listItems = this.listItems.filter(i => i !== item);
11324
- this.renderList$.next();
11325
- }
11968
+ ngOnInit() {
11969
+ this.allTags$ = this.dataService.product
11970
+ .getTagList()
11971
+ .mapStream(data => data.tags.items.map(i => i.value));
11326
11972
  }
11327
- renderInputComponent(factory, viewContainerRef, formControl) {
11328
- const componentRef = viewContainerRef.createComponent(factory);
11329
- const { instance } = componentRef;
11330
- instance.config = simpleDeepClone(this.def);
11331
- instance.formControl = formControl;
11332
- instance.readonly = this.readonly;
11333
- componentRef.injector.get(ChangeDetectorRef).markForCheck();
11334
- return componentRef;
11973
+ addTagFn(val) {
11974
+ return val;
11335
11975
  }
11336
11976
  registerOnChange(fn) {
11337
11977
  this.onChange = fn;
@@ -11339,102 +11979,100 @@ class DynamicFormInputComponent {
11339
11979
  registerOnTouched(fn) {
11340
11980
  this.onTouch = fn;
11341
11981
  }
11982
+ setDisabledState(isDisabled) {
11983
+ this.disabled = isDisabled;
11984
+ }
11342
11985
  writeValue(obj) {
11343
11986
  if (Array.isArray(obj)) {
11344
- if (obj.length === this.listItems.length) {
11345
- obj.forEach((value, index) => {
11346
- var _a;
11347
- const control = (_a = this.listItems[index]) === null || _a === void 0 ? void 0 : _a.control;
11348
- control.patchValue(getConfigArgValue(value), { emitEvent: false });
11349
- });
11350
- }
11351
- else {
11352
- this.listItems = obj.map(value => ({
11353
- id: this.listId++,
11354
- control: new FormControl(getConfigArgValue(value)),
11355
- }));
11356
- this.renderList$.next();
11357
- }
11358
- }
11359
- else {
11360
- this.listItems = [];
11361
- this.renderList$.next();
11362
- }
11363
- this.changeDetectorRef.markForCheck();
11364
- }
11365
- getInputComponentConfig(argDef) {
11366
- var _a;
11367
- if (this.hasUiConfig(argDef) && argDef.ui.component) {
11368
- return argDef.ui;
11369
- }
11370
- const type = argDef === null || argDef === void 0 ? void 0 : argDef.type;
11371
- switch (type) {
11372
- case 'string':
11373
- case 'localeString': {
11374
- const hasOptions = !!(this.isConfigArgDef(argDef) && ((_a = argDef.ui) === null || _a === void 0 ? void 0 : _a.options)) ||
11375
- !!argDef.options;
11376
- if (hasOptions) {
11377
- return { component: 'select-form-input' };
11378
- }
11379
- else {
11380
- return { component: 'text-form-input' };
11381
- }
11382
- }
11383
- case 'text': {
11384
- return { component: 'textarea-form-input' };
11385
- }
11386
- case 'int':
11387
- case 'float':
11388
- return { component: 'number-form-input' };
11389
- case 'boolean':
11390
- return { component: 'boolean-form-input' };
11391
- case 'datetime':
11392
- return { component: 'date-form-input' };
11393
- case 'ID':
11394
- return { component: 'text-form-input' };
11395
- case 'relation':
11396
- return { component: 'relation-form-input' };
11397
- default:
11398
- assertNever(type);
11987
+ this._value = obj;
11399
11988
  }
11400
11989
  }
11401
- isConfigArgDef(def) {
11402
- return (def === null || def === void 0 ? void 0 : def.__typename) === 'ConfigArgDefinition';
11403
- }
11404
- hasUiConfig(def) {
11405
- var _a;
11406
- return typeof def === 'object' && typeof ((_a = def === null || def === void 0 ? void 0 : def.ui) === null || _a === void 0 ? void 0 : _a.component) === 'string';
11990
+ valueChanged(event) {
11991
+ this.onChange(event);
11407
11992
  }
11408
11993
  }
11409
- DynamicFormInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: DynamicFormInputComponent, deps: [{ token: ComponentRegistryService }, { token: i0.ComponentFactoryResolver }, { token: i0.ChangeDetectorRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component });
11410
- DynamicFormInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: DynamicFormInputComponent, selector: "vdr-dynamic-form-input", inputs: { def: "def", readonly: "readonly", control: "control" }, providers: [
11994
+ TagSelectorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: TagSelectorComponent, deps: [{ token: DataService }], target: i0.ɵɵFactoryTarget.Component });
11995
+ TagSelectorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: TagSelectorComponent, selector: "vdr-tag-selector", inputs: { placeholder: "placeholder" }, providers: [
11411
11996
  {
11412
11997
  provide: NG_VALUE_ACCESSOR,
11413
- useExisting: DynamicFormInputComponent,
11998
+ useExisting: TagSelectorComponent,
11414
11999
  multi: true,
11415
12000
  },
11416
- ], viewQueries: [{ propertyName: "singleViewContainer", first: true, predicate: ["single"], descendants: true, read: ViewContainerRef }, { propertyName: "listItemContainers", predicate: ["listItem"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"!renderAsList; else list\">\r\n <ng-container #single></ng-container>\r\n</ng-container>\r\n<ng-template #list>\r\n <div class=\"list-container\" cdkDropList (cdkDropListDropped)=\"moveListItem($event)\">\r\n <div class=\"list-item-row\" *ngFor=\"let item of listItems; trackBy: trackById\" cdkDrag [cdkDragData]=\"item\">\r\n <ng-container #listItem></ng-container>\r\n <button class=\"btn btn-link btn-sm btn-warning\" (click)=\"removeListItem(item)\" [title]=\"'common.remove-item-from-list' | translate\">\r\n <clr-icon shape=\"times\"></clr-icon>\r\n </button>\r\n <div class=\"flex-spacer\"></div>\r\n <div class=\"drag-handle\" cdkDragHandle *ngIf=\"!readonly\">\r\n <clr-icon shape=\"drag-handle\" size=\"24\"></clr-icon>\r\n </div>\r\n </div>\r\n <button class=\"btn btn-secondary btn-sm\" (click)=\"addListItem()\">\r\n <clr-icon shape=\"plus\"></clr-icon> {{ 'common.add-item-to-list' | translate }}\r\n </button>\r\n </div>\r\n</ng-template>\r\n", styles: [":host{flex:1}.list-container{border:1px solid var(--color-component-border-200);border-radius:3px;padding:12px}.list-item-row{font-size:13px;display:flex;align-items:center;margin:3px 0}.drag-placeholder{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-preview{font-size:13px;background-color:var(--color-component-bg-100);opacity:.8;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:.1}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .list-item-row:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3$1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$3.ClrDatagridItemsTrackBy, selector: "[ngForTrackBy]", inputs: ["ngForTrackBy"] }, { type: i3$1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i3$1.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }], pipes: { "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11417
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: DynamicFormInputComponent, decorators: [{
12001
+ ], ngImport: i0, template: "<ng-select\r\n [addTag]=\"addTagFn\"\r\n [multiple]=\"true\"\r\n [ngModel]=\"_value\"\r\n [clearable]=\"true\"\r\n [searchable]=\"true\"\r\n [disabled]=\"disabled\"\r\n [placeholder]=\"placeholder\"\r\n (change)=\"valueChanged($event)\"\r\n>\r\n <ng-template ng-label-tmp let-tag=\"item\" let-clear=\"clear\">\r\n <vdr-chip [colorFrom]=\"tag\" icon=\"close\" (iconClick)=\"clear(tag)\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag }}</vdr-chip>\r\n </ng-template>\r\n <ng-option *ngFor=\"let tag of allTags$ | async\" [value]=\"tag\">\r\n <vdr-chip [colorFrom]=\"tag\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag }}</vdr-chip>\r\n </ng-option>\r\n</ng-select>\r\n", styles: [":host{display:block;margin-top:12px;position:relative}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background:none;margin:0}:host ::ng-deep .ng-dropdown-panel-items div.ng-option:last-child{display:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border:none;padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-left:8px}\n"], components: [{ type: i2$1.NgSelectComponent, selector: "ng-select", inputs: ["bindLabel", "bindValue", "markFirst", "placeholder", "notFoundText", "typeToSearchText", "addTagText", "loadingText", "clearAllText", "appearance", "dropdownPosition", "appendTo", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "keyDownFn", "typeahead", "multiple", "addTag", "searchable", "clearable", "isOpen", "items", "compareWith", "clearSearchOnAdd"], outputs: ["blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"] }, { type: ChipComponent, selector: "vdr-chip", inputs: ["icon", "invert", "colorFrom", "colorType"], outputs: ["iconClick"] }, { type: i2$1.NgOptionComponent, selector: "ng-option", inputs: ["value", "disabled"] }], directives: [{ type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i2$1.NgLabelTemplateDirective, selector: "[ng-label-tmp]" }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i3.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
12002
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: TagSelectorComponent, decorators: [{
11418
12003
  type: Component,
11419
- args: [{ selector: 'vdr-dynamic-form-input', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
12004
+ args: [{ selector: 'vdr-tag-selector', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
11420
12005
  {
11421
12006
  provide: NG_VALUE_ACCESSOR,
11422
- useExisting: DynamicFormInputComponent,
12007
+ useExisting: TagSelectorComponent,
11423
12008
  multi: true,
11424
12009
  },
11425
- ], template: "<ng-container *ngIf=\"!renderAsList; else list\">\r\n <ng-container #single></ng-container>\r\n</ng-container>\r\n<ng-template #list>\r\n <div class=\"list-container\" cdkDropList (cdkDropListDropped)=\"moveListItem($event)\">\r\n <div class=\"list-item-row\" *ngFor=\"let item of listItems; trackBy: trackById\" cdkDrag [cdkDragData]=\"item\">\r\n <ng-container #listItem></ng-container>\r\n <button class=\"btn btn-link btn-sm btn-warning\" (click)=\"removeListItem(item)\" [title]=\"'common.remove-item-from-list' | translate\">\r\n <clr-icon shape=\"times\"></clr-icon>\r\n </button>\r\n <div class=\"flex-spacer\"></div>\r\n <div class=\"drag-handle\" cdkDragHandle *ngIf=\"!readonly\">\r\n <clr-icon shape=\"drag-handle\" size=\"24\"></clr-icon>\r\n </div>\r\n </div>\r\n <button class=\"btn btn-secondary btn-sm\" (click)=\"addListItem()\">\r\n <clr-icon shape=\"plus\"></clr-icon> {{ 'common.add-item-to-list' | translate }}\r\n </button>\r\n </div>\r\n</ng-template>\r\n", styles: [":host{flex:1}.list-container{border:1px solid var(--color-component-border-200);border-radius:3px;padding:12px}.list-item-row{font-size:13px;display:flex;align-items:center;margin:3px 0}.drag-placeholder{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drag-preview{font-size:13px;background-color:var(--color-component-bg-100);opacity:.8;border-radius:4px;box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.cdk-drag-placeholder{opacity:.1}.cdk-drag-animating{transition:transform .25s cubic-bezier(0,0,.2,1)}.cdk-drop-list-dragging .list-item-row:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}\n"] }]
11426
- }], ctorParameters: function () { return [{ type: ComponentRegistryService }, { type: i0.ComponentFactoryResolver }, { type: i0.ChangeDetectorRef }, { type: i0.Injector }]; }, propDecorators: { def: [{
12010
+ ], template: "<ng-select\r\n [addTag]=\"addTagFn\"\r\n [multiple]=\"true\"\r\n [ngModel]=\"_value\"\r\n [clearable]=\"true\"\r\n [searchable]=\"true\"\r\n [disabled]=\"disabled\"\r\n [placeholder]=\"placeholder\"\r\n (change)=\"valueChanged($event)\"\r\n>\r\n <ng-template ng-label-tmp let-tag=\"item\" let-clear=\"clear\">\r\n <vdr-chip [colorFrom]=\"tag\" icon=\"close\" (iconClick)=\"clear(tag)\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag }}</vdr-chip>\r\n </ng-template>\r\n <ng-option *ngFor=\"let tag of allTags$ | async\" [value]=\"tag\">\r\n <vdr-chip [colorFrom]=\"tag\"><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag }}</vdr-chip>\r\n </ng-option>\r\n</ng-select>\r\n", styles: [":host{display:block;margin-top:12px;position:relative}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-value{background:none;margin:0}:host ::ng-deep .ng-dropdown-panel-items div.ng-option:last-child{display:none}:host ::ng-deep .ng-dropdown-panel .ng-dropdown-header{border:none;padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container{padding:0}:host ::ng-deep .ng-select.ng-select-multiple .ng-select-container .ng-value-container .ng-placeholder{padding-left:8px}\n"] }]
12011
+ }], ctorParameters: function () { return [{ type: DataService }]; }, propDecorators: { placeholder: [{
11427
12012
  type: Input
11428
- }], readonly: [{
12013
+ }] } });
12014
+
12015
+ /**
12016
+ * A form field wrapper which handles the correct layout and validation error display for
12017
+ * a form control.
12018
+ */
12019
+ class FormFieldComponent {
12020
+ constructor() {
12021
+ /**
12022
+ * A map of error message codes (required, pattern etc.) to messages to display
12023
+ * when those errors are present.
12024
+ */
12025
+ this.errors = {};
12026
+ /**
12027
+ * If set to true, the input will be initially set to "readOnly", and an "edit" button
12028
+ * will be displayed which allows the field to be edited.
12029
+ */
12030
+ this.readOnlyToggle = false;
12031
+ this.isReadOnly = false;
12032
+ }
12033
+ ngOnInit() {
12034
+ if (this.readOnlyToggle) {
12035
+ this.isReadOnly = true;
12036
+ this.setReadOnly(true);
12037
+ }
12038
+ this.isReadOnly = this.readOnlyToggle;
12039
+ }
12040
+ setReadOnly(value) {
12041
+ this.formFieldControl.setReadOnly(value);
12042
+ this.isReadOnly = value;
12043
+ }
12044
+ getErrorMessage() {
12045
+ if (!this.formFieldControl || !this.formFieldControl.formControlName) {
12046
+ return;
12047
+ }
12048
+ const errors = this.formFieldControl.formControlName.errors;
12049
+ if (errors) {
12050
+ for (const errorKey of Object.keys(errors)) {
12051
+ if (this.errors[errorKey]) {
12052
+ return this.errors[errorKey];
12053
+ }
12054
+ }
12055
+ }
12056
+ }
12057
+ }
12058
+ FormFieldComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: FormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12059
+ FormFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: FormFieldComponent, selector: "vdr-form-field", inputs: { label: "label", for: "for", tooltip: "tooltip", errors: "errors", readOnlyToggle: "readOnlyToggle" }, queries: [{ propertyName: "formFieldControl", first: true, predicate: FormFieldControlDirective, descendants: true, static: true }], ngImport: i0, template: "<div\r\n class=\"form-group\"\r\n [class.no-label]=\"!label\"\r\n [class.clr-error]=\"formFieldControl?.formControlName?.invalid\"\r\n>\r\n <label *ngIf=\"label\" [for]=\"for\" class=\"clr-control-label\">\r\n {{ label }}\r\n <vdr-help-tooltip *ngIf=\"tooltip\" [content]=\"tooltip\"></vdr-help-tooltip>\r\n </label>\r\n <label\r\n [for]=\"for\"\r\n aria-haspopup=\"true\"\r\n role=\"tooltip\"\r\n [class.invalid]=\"formFieldControl?.touched && !formFieldControl?.valid\"\r\n class=\"tooltip tooltip-validation tooltip-sm tooltip-top-left\"\r\n >\r\n <div class=\"input-row\" [class.has-toggle]=\"readOnlyToggle\">\r\n <ng-content></ng-content>\r\n <button\r\n *ngIf=\"readOnlyToggle\"\r\n type=\"button\"\r\n [disabled]=\"!isReadOnly\"\r\n [title]=\"'common.edit-field' | translate\"\r\n class=\"btn btn-icon edit-button\"\r\n (click)=\"setReadOnly(false)\"\r\n >\r\n <clr-icon shape=\"edit\"></clr-icon>\r\n </button>\r\n </div>\r\n <div class=\"clr-subtext\" *ngIf=\"getErrorMessage()\">{{ getErrorMessage() }}</div>\r\n <span class=\"tooltip-content\">{{ label }} is required.</span>\r\n </label>\r\n</div>\r\n", styles: [":host{display:block}:host .form-group>label:first-child{top:6px}:host .form-group>label:nth-of-type(2){flex:1;max-width:20rem}:host .form-group>label:nth-of-type(2) ::ng-deep>*:not(.tooltip-content){width:100%}:host .form-group .tooltip-validation{height:initial}:host .form-group.no-label{margin:-6px 0 0;padding:0;justify-content:center}:host .form-group.no-label>label{position:relative;justify-content:center}:host .form-group.no-label .input-row{justify-content:center}:host .input-row{display:flex}:host .input-row ::ng-deep input{flex:1}:host .input-row ::ng-deep input[disabled]{background-color:var(--color-component-bg-200)}:host .input-row button.edit-button{margin:0;border-radius:0 3px 3px 0}:host .input-row.has-toggle ::ng-deep input{border-top-right-radius:0!important;border-bottom-right-radius:0!important;border-right:none}:host .input-row ::ng-deep clr-toggle-wrapper{margin-top:8px}.tooltip.tooltip-validation.invalid:before{position:absolute;content:\"\";height:.666667rem;width:.666667rem;top:.125rem;right:.25rem;background-image:url(data:image/svg+xml;charset=utf8,%3Csvg%20version%3D%221.1%22%20viewBox%3D%225%205%2026%2026%22%20preserveAspectRatio%3D%22xMidYMid%20meet%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%3Cdefs%3E%3Cstyle%3E.clr-i-outline%7Bfill%3A%23a32100%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctitle%3Eexclamation-circle-line%3C%2Ftitle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20class%3D%22clr-i-outline%20clr-i-outline-path-1%22%20d%3D%22M18%2C6A12%2C12%2C0%2C1%2C0%2C30%2C18%2C12%2C12%2C0%2C0%2C0%2C18%2C6Zm0%2C22A10%2C10%2C0%2C1%2C1%2C28%2C18%2C10%2C10%2C0%2C0%2C1%2C18%2C28Z%22%3E%3C%2Fpath%3E%3Cpath%20class%3D%22clr-i-outline%20clr-i-outline-path-2%22%20d%3D%22M18%2C20.07a1.3%2C1.3%2C0%2C0%2C1-1.3-1.3v-6a1.3%2C1.3%2C0%2C1%2C1%2C2.6%2C0v6A1.3%2C1.3%2C0%2C0%2C1%2C18%2C20.07Z%22%3E%3C%2Fpath%3E%3Ccircle%20class%3D%22clr-i-outline%20clr-i-outline-path-3%22%20cx%3D%2217.95%22%20cy%3D%2223.02%22%20r%3D%221.5%22%3E%3C%2Fcircle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fsvg%3E);background-repeat:no-repeat;background-size:contain;vertical-align:middle;margin:0}.tooltip.tooltip-sm>.tooltip-content,.tooltip .tooltip-content.tooltip-sm{width:5rem}.tooltip:hover>.tooltip-content{right:12px;margin-bottom:0}.tooltip:not(.invalid):hover>.tooltip-content{display:none}\n"], components: [{ type: HelpTooltipComponent, selector: "vdr-help-tooltip", inputs: ["content", "position"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$3.ClrLabel, selector: "label", inputs: ["for"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }], pipes: { "translate": i7.TranslatePipe } });
12060
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: FormFieldComponent, decorators: [{
12061
+ type: Component,
12062
+ args: [{ selector: 'vdr-form-field', template: "<div\r\n class=\"form-group\"\r\n [class.no-label]=\"!label\"\r\n [class.clr-error]=\"formFieldControl?.formControlName?.invalid\"\r\n>\r\n <label *ngIf=\"label\" [for]=\"for\" class=\"clr-control-label\">\r\n {{ label }}\r\n <vdr-help-tooltip *ngIf=\"tooltip\" [content]=\"tooltip\"></vdr-help-tooltip>\r\n </label>\r\n <label\r\n [for]=\"for\"\r\n aria-haspopup=\"true\"\r\n role=\"tooltip\"\r\n [class.invalid]=\"formFieldControl?.touched && !formFieldControl?.valid\"\r\n class=\"tooltip tooltip-validation tooltip-sm tooltip-top-left\"\r\n >\r\n <div class=\"input-row\" [class.has-toggle]=\"readOnlyToggle\">\r\n <ng-content></ng-content>\r\n <button\r\n *ngIf=\"readOnlyToggle\"\r\n type=\"button\"\r\n [disabled]=\"!isReadOnly\"\r\n [title]=\"'common.edit-field' | translate\"\r\n class=\"btn btn-icon edit-button\"\r\n (click)=\"setReadOnly(false)\"\r\n >\r\n <clr-icon shape=\"edit\"></clr-icon>\r\n </button>\r\n </div>\r\n <div class=\"clr-subtext\" *ngIf=\"getErrorMessage()\">{{ getErrorMessage() }}</div>\r\n <span class=\"tooltip-content\">{{ label }} is required.</span>\r\n </label>\r\n</div>\r\n", styles: [":host{display:block}:host .form-group>label:first-child{top:6px}:host .form-group>label:nth-of-type(2){flex:1;max-width:20rem}:host .form-group>label:nth-of-type(2) ::ng-deep>*:not(.tooltip-content){width:100%}:host .form-group .tooltip-validation{height:initial}:host .form-group.no-label{margin:-6px 0 0;padding:0;justify-content:center}:host .form-group.no-label>label{position:relative;justify-content:center}:host .form-group.no-label .input-row{justify-content:center}:host .input-row{display:flex}:host .input-row ::ng-deep input{flex:1}:host .input-row ::ng-deep input[disabled]{background-color:var(--color-component-bg-200)}:host .input-row button.edit-button{margin:0;border-radius:0 3px 3px 0}:host .input-row.has-toggle ::ng-deep input{border-top-right-radius:0!important;border-bottom-right-radius:0!important;border-right:none}:host .input-row ::ng-deep clr-toggle-wrapper{margin-top:8px}.tooltip.tooltip-validation.invalid:before{position:absolute;content:\"\";height:.666667rem;width:.666667rem;top:.125rem;right:.25rem;background-image:url(data:image/svg+xml;charset=utf8,%3Csvg%20version%3D%221.1%22%20viewBox%3D%225%205%2026%2026%22%20preserveAspectRatio%3D%22xMidYMid%20meet%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%3Cdefs%3E%3Cstyle%3E.clr-i-outline%7Bfill%3A%23a32100%3B%7D%3C%2Fstyle%3E%3C%2Fdefs%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctitle%3Eexclamation-circle-line%3C%2Ftitle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cpath%20class%3D%22clr-i-outline%20clr-i-outline-path-1%22%20d%3D%22M18%2C6A12%2C12%2C0%2C1%2C0%2C30%2C18%2C12%2C12%2C0%2C0%2C0%2C18%2C6Zm0%2C22A10%2C10%2C0%2C1%2C1%2C28%2C18%2C10%2C10%2C0%2C0%2C1%2C18%2C28Z%22%3E%3C%2Fpath%3E%3Cpath%20class%3D%22clr-i-outline%20clr-i-outline-path-2%22%20d%3D%22M18%2C20.07a1.3%2C1.3%2C0%2C0%2C1-1.3-1.3v-6a1.3%2C1.3%2C0%2C1%2C1%2C2.6%2C0v6A1.3%2C1.3%2C0%2C0%2C1%2C18%2C20.07Z%22%3E%3C%2Fpath%3E%3Ccircle%20class%3D%22clr-i-outline%20clr-i-outline-path-3%22%20cx%3D%2217.95%22%20cy%3D%2223.02%22%20r%3D%221.5%22%3E%3C%2Fcircle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fsvg%3E);background-repeat:no-repeat;background-size:contain;vertical-align:middle;margin:0}.tooltip.tooltip-sm>.tooltip-content,.tooltip .tooltip-content.tooltip-sm{width:5rem}.tooltip:hover>.tooltip-content{right:12px;margin-bottom:0}.tooltip:not(.invalid):hover>.tooltip-content{display:none}\n"] }]
12063
+ }], propDecorators: { label: [{
11429
12064
  type: Input
11430
- }], control: [{
12065
+ }], for: [{
11431
12066
  type: Input
11432
- }], singleViewContainer: [{
11433
- type: ViewChild,
11434
- args: ['single', { read: ViewContainerRef }]
11435
- }], listItemContainers: [{
11436
- type: ViewChildren,
11437
- args: ['listItem', { read: ViewContainerRef }]
12067
+ }], tooltip: [{
12068
+ type: Input
12069
+ }], errors: [{
12070
+ type: Input
12071
+ }], readOnlyToggle: [{
12072
+ type: Input
12073
+ }], formFieldControl: [{
12074
+ type: ContentChild,
12075
+ args: [FormFieldControlDirective, { static: true }]
11438
12076
  }] } });
11439
12077
 
11440
12078
  /**
@@ -11924,11 +12562,15 @@ class AssetGalleryComponent {
11924
12562
  this.canDelete = false;
11925
12563
  this.selectionChange = new EventEmitter();
11926
12564
  this.deleteAssets = new EventEmitter();
11927
- this.selection = [];
12565
+ this.selectionManager = new SelectionManager({
12566
+ multiSelect: this.multiSelect,
12567
+ itemsAreEqual: (a, b) => a.id === b.id,
12568
+ additiveMode: false,
12569
+ });
11928
12570
  }
11929
- ngOnChanges() {
12571
+ ngOnChanges(changes) {
11930
12572
  if (this.assets) {
11931
- for (const asset of this.selection) {
12573
+ for (const asset of this.selectionManager.selection) {
11932
12574
  // Update and selected assets with any changes
11933
12575
  const match = this.assets.find(a => a.id === asset.id);
11934
12576
  if (match) {
@@ -11936,49 +12578,26 @@ class AssetGalleryComponent {
11936
12578
  }
11937
12579
  }
11938
12580
  }
11939
- }
11940
- toggleSelection(asset, event) {
11941
- const index = this.selection.findIndex(a => a.id === asset.id);
11942
- if (this.multiSelect && (event === null || event === void 0 ? void 0 : event.shiftKey) && 1 <= this.selection.length) {
11943
- const lastSelection = this.selection[this.selection.length - 1];
11944
- const lastSelectionIndex = this.assets.findIndex(a => a.id === lastSelection.id);
11945
- const currentIndex = this.assets.findIndex(a => a.id === asset.id);
11946
- const start = currentIndex < lastSelectionIndex ? currentIndex : lastSelectionIndex;
11947
- const end = currentIndex > lastSelectionIndex ? currentIndex + 1 : lastSelectionIndex;
11948
- this.selection.push(...this.assets.slice(start, end).filter(a => !this.selection.find(s => s.id === a.id)));
11949
- }
11950
- else if (index === -1) {
11951
- if (this.multiSelect && ((event === null || event === void 0 ? void 0 : event.ctrlKey) || (event === null || event === void 0 ? void 0 : event.shiftKey))) {
11952
- this.selection.push(asset);
11953
- }
11954
- else {
11955
- this.selection = [asset];
11956
- }
12581
+ if (changes['assets']) {
12582
+ this.selectionManager.setCurrentItems(this.assets);
11957
12583
  }
11958
- else {
11959
- if (this.multiSelect && (event === null || event === void 0 ? void 0 : event.ctrlKey)) {
11960
- this.selection.splice(index, 1);
11961
- }
11962
- else if (1 < this.selection.length) {
11963
- this.selection = [asset];
11964
- }
11965
- else {
11966
- this.selection.splice(index, 1);
11967
- }
12584
+ if (changes['multiSelect']) {
12585
+ this.selectionManager.setMultiSelect(this.multiSelect);
11968
12586
  }
11969
- // Make the selection mutable
11970
- this.selection = this.selection.map(x => (Object.assign({}, x)));
11971
- this.selectionChange.emit(this.selection);
12587
+ }
12588
+ toggleSelection(asset, event) {
12589
+ this.selectionManager.toggleSelection(asset, event);
12590
+ this.selectionChange.emit(this.selectionManager.selection);
11972
12591
  }
11973
12592
  selectMultiple(assets) {
11974
- this.selection = assets;
11975
- this.selectionChange.emit(this.selection);
12593
+ this.selectionManager.selectMultiple(assets);
12594
+ this.selectionChange.emit(this.selectionManager.selection);
11976
12595
  }
11977
12596
  isSelected(asset) {
11978
- return !!this.selection.find(a => a.id === asset.id);
12597
+ return this.selectionManager.isSelected(asset);
11979
12598
  }
11980
12599
  lastSelected() {
11981
- return this.selection[this.selection.length - 1];
12600
+ return this.selectionManager.lastSelected();
11982
12601
  }
11983
12602
  previewAsset(asset) {
11984
12603
  this.modalService
@@ -11987,69 +12606,27 @@ class AssetGalleryComponent {
11987
12606
  closable: true,
11988
12607
  locals: { asset },
11989
12608
  })
11990
- .subscribe();
11991
- }
11992
- entityInfoClick(event) {
11993
- event.preventDefault();
11994
- event.stopPropagation();
11995
- }
11996
- }
11997
- AssetGalleryComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetGalleryComponent, deps: [{ token: ModalService }], target: i0.ɵɵFactoryTarget.Component });
11998
- AssetGalleryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: AssetGalleryComponent, selector: "vdr-asset-gallery", inputs: { assets: "assets", multiSelect: "multiSelect", canDelete: "canDelete" }, outputs: { selectionChange: "selectionChange", deleteAssets: "deleteAssets" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"gallery\">\r\n <div\r\n class=\"card\"\r\n *ngFor=\"let asset of assets\"\r\n (click)=\"toggleSelection(asset, $event)\"\r\n [class.selected]=\"isSelected(asset)\"\r\n >\r\n <div class=\"card-img\">\r\n <div class=\"selected-checkbox\"><clr-icon shape=\"check-circle\" size=\"32\"></clr-icon></div>\r\n <img [src]=\"asset | assetPreview: 'thumb'\" />\r\n </div>\r\n <div class=\"detail\">\r\n <vdr-entity-info\r\n [entity]=\"asset\"\r\n [small]=\"true\"\r\n (click)=\"entityInfoClick($event)\"\r\n ></vdr-entity-info>\r\n <span [title]=\"asset.name\">{{ asset.name }}</span>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"info-bar\">\r\n <div class=\"card\">\r\n <div class=\"card-img\">\r\n <div class=\"placeholder\" *ngIf=\"selection.length === 0\">\r\n <clr-icon shape=\"image\" size=\"128\"></clr-icon>\r\n <div>{{ 'catalog.no-selection' | translate }}</div>\r\n </div>\r\n <img\r\n class=\"preview\"\r\n *ngIf=\"selection.length >= 1\"\r\n [src]=\"lastSelected().preview + '?preset=medium'\"\r\n />\r\n </div>\r\n <div class=\"card-block details\" *ngIf=\"selection.length >= 1\">\r\n <div class=\"name\">{{ lastSelected().name }}</div>\r\n <div>{{ 'asset.original-asset-size' | translate }}: {{ lastSelected().fileSize | filesize }}</div>\r\n\r\n <ng-container *ngIf=\"selection.length === 1\">\r\n <vdr-chip *ngFor=\"let tag of lastSelected().tags\" [colorFrom]=\"tag.value\"\r\n ><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag.value }}</vdr-chip\r\n >\r\n <div>\r\n <button (click)=\"previewAsset(lastSelected())\" class=\"btn btn-link\">\r\n <clr-icon shape=\"eye\"></clr-icon> {{ 'asset.preview' | translate }}\r\n </button>\r\n </div>\r\n <div>\r\n <vdr-asset-preview-links class=\"\" [asset]=\"lastSelected()\"></vdr-asset-preview-links>\r\n </div>\r\n <div>\r\n <a [routerLink]=\"['./', lastSelected().id]\" class=\"btn btn-link\">\r\n <clr-icon shape=\"pencil\"></clr-icon> {{ 'common.edit' | translate }}\r\n </a>\r\n </div>\r\n </ng-container>\r\n <div *ngIf=\"canDelete\">\r\n <button (click)=\"deleteAssets.emit(selection)\" class=\"btn btn-link\">\r\n <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon> {{ 'common.delete' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card stack\" [class.visible]=\"selection.length > 1\"></div>\r\n <div class=\"selection-count\" [class.visible]=\"selection.length > 1\">\r\n {{ 'asset.assets-selected-count' | translate: { count: selection.length } }}\r\n <ul>\r\n <li *ngFor=\"let asset of selection\">{{ asset.name }}</li>\r\n </ul>\r\n </div>\r\n</div>\r\n", styles: [":host{display:flex;overflow:hidden}.gallery{flex:1;display:grid;grid-template-columns:repeat(auto-fill,150px);grid-template-rows:repeat(auto-fill,180px);grid-gap:10px 20px;overflow-y:auto;padding-left:12px;padding-top:12px;padding-bottom:12px}.gallery .card:hover{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.card{margin-top:0;position:relative}.selected-checkbox{opacity:0;position:absolute;color:var(--color-success-500);background-color:#fff;border-radius:50%;top:-12px;left:-12px;box-shadow:0 5px 5px -4px #000000bf;transition:opacity .1s}.card.selected{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.card.selected .selected-checkbox{opacity:1}.detail{font-size:12px;margin:3px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.detail vdr-entity-info{height:16px}.info-bar{width:25%;padding:0 6px;overflow-y:auto}.info-bar .card{z-index:1}.info-bar .stack{z-index:0;opacity:0;transform:perspective(500px) translateZ(0) translateY(-16px);height:16px;transition:transform .3s,opacity 0s .3s;background-color:#fff}.info-bar .stack.visible{opacity:1;transform:perspective(500px) translateZ(-44px) translateY(0);background-color:var(--color-component-bg-100);transition:transform .3s,color .3s}.info-bar .selection-count{opacity:0;position:relative;text-align:center;visibility:hidden;transition:opacity .3s,visibility 0s .3s}.info-bar .selection-count.visible{opacity:1;visibility:visible;transition:opacity .3s,visibility 0s}.info-bar .selection-count ul{text-align:left;list-style-type:none;margin-left:12px}.info-bar .selection-count ul li{font-size:12px}.info-bar .placeholder{text-align:center;color:var(--color-grey-300)}.info-bar .preview img{max-width:100%}.info-bar .details{font-size:12px;word-break:break-all}.info-bar .name{line-height:14px;font-weight:700}\n"], components: [{ type: EntityInfoComponent, selector: "vdr-entity-info", inputs: ["small", "entity"] }, { type: ChipComponent, selector: "vdr-chip", inputs: ["icon", "invert", "colorFrom", "colorType"], outputs: ["iconClick"] }, { type: AssetPreviewLinksComponent, selector: "vdr-asset-preview-links", inputs: ["asset"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$2.RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "preserveFragment", "skipLocationChange", "replaceUrl", "state", "relativeTo", "routerLink"] }], pipes: { "assetPreview": AssetPreviewPipe, "translate": i7.TranslatePipe, "filesize": FileSizePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
11999
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetGalleryComponent, decorators: [{
12000
- type: Component,
12001
- args: [{ selector: 'vdr-asset-gallery', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gallery\">\r\n <div\r\n class=\"card\"\r\n *ngFor=\"let asset of assets\"\r\n (click)=\"toggleSelection(asset, $event)\"\r\n [class.selected]=\"isSelected(asset)\"\r\n >\r\n <div class=\"card-img\">\r\n <div class=\"selected-checkbox\"><clr-icon shape=\"check-circle\" size=\"32\"></clr-icon></div>\r\n <img [src]=\"asset | assetPreview: 'thumb'\" />\r\n </div>\r\n <div class=\"detail\">\r\n <vdr-entity-info\r\n [entity]=\"asset\"\r\n [small]=\"true\"\r\n (click)=\"entityInfoClick($event)\"\r\n ></vdr-entity-info>\r\n <span [title]=\"asset.name\">{{ asset.name }}</span>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"info-bar\">\r\n <div class=\"card\">\r\n <div class=\"card-img\">\r\n <div class=\"placeholder\" *ngIf=\"selection.length === 0\">\r\n <clr-icon shape=\"image\" size=\"128\"></clr-icon>\r\n <div>{{ 'catalog.no-selection' | translate }}</div>\r\n </div>\r\n <img\r\n class=\"preview\"\r\n *ngIf=\"selection.length >= 1\"\r\n [src]=\"lastSelected().preview + '?preset=medium'\"\r\n />\r\n </div>\r\n <div class=\"card-block details\" *ngIf=\"selection.length >= 1\">\r\n <div class=\"name\">{{ lastSelected().name }}</div>\r\n <div>{{ 'asset.original-asset-size' | translate }}: {{ lastSelected().fileSize | filesize }}</div>\r\n\r\n <ng-container *ngIf=\"selection.length === 1\">\r\n <vdr-chip *ngFor=\"let tag of lastSelected().tags\" [colorFrom]=\"tag.value\"\r\n ><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag.value }}</vdr-chip\r\n >\r\n <div>\r\n <button (click)=\"previewAsset(lastSelected())\" class=\"btn btn-link\">\r\n <clr-icon shape=\"eye\"></clr-icon> {{ 'asset.preview' | translate }}\r\n </button>\r\n </div>\r\n <div>\r\n <vdr-asset-preview-links class=\"\" [asset]=\"lastSelected()\"></vdr-asset-preview-links>\r\n </div>\r\n <div>\r\n <a [routerLink]=\"['./', lastSelected().id]\" class=\"btn btn-link\">\r\n <clr-icon shape=\"pencil\"></clr-icon> {{ 'common.edit' | translate }}\r\n </a>\r\n </div>\r\n </ng-container>\r\n <div *ngIf=\"canDelete\">\r\n <button (click)=\"deleteAssets.emit(selection)\" class=\"btn btn-link\">\r\n <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon> {{ 'common.delete' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card stack\" [class.visible]=\"selection.length > 1\"></div>\r\n <div class=\"selection-count\" [class.visible]=\"selection.length > 1\">\r\n {{ 'asset.assets-selected-count' | translate: { count: selection.length } }}\r\n <ul>\r\n <li *ngFor=\"let asset of selection\">{{ asset.name }}</li>\r\n </ul>\r\n </div>\r\n</div>\r\n", styles: [":host{display:flex;overflow:hidden}.gallery{flex:1;display:grid;grid-template-columns:repeat(auto-fill,150px);grid-template-rows:repeat(auto-fill,180px);grid-gap:10px 20px;overflow-y:auto;padding-left:12px;padding-top:12px;padding-bottom:12px}.gallery .card:hover{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.card{margin-top:0;position:relative}.selected-checkbox{opacity:0;position:absolute;color:var(--color-success-500);background-color:#fff;border-radius:50%;top:-12px;left:-12px;box-shadow:0 5px 5px -4px #000000bf;transition:opacity .1s}.card.selected{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.card.selected .selected-checkbox{opacity:1}.detail{font-size:12px;margin:3px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.detail vdr-entity-info{height:16px}.info-bar{width:25%;padding:0 6px;overflow-y:auto}.info-bar .card{z-index:1}.info-bar .stack{z-index:0;opacity:0;transform:perspective(500px) translateZ(0) translateY(-16px);height:16px;transition:transform .3s,opacity 0s .3s;background-color:#fff}.info-bar .stack.visible{opacity:1;transform:perspective(500px) translateZ(-44px) translateY(0);background-color:var(--color-component-bg-100);transition:transform .3s,color .3s}.info-bar .selection-count{opacity:0;position:relative;text-align:center;visibility:hidden;transition:opacity .3s,visibility 0s .3s}.info-bar .selection-count.visible{opacity:1;visibility:visible;transition:opacity .3s,visibility 0s}.info-bar .selection-count ul{text-align:left;list-style-type:none;margin-left:12px}.info-bar .selection-count ul li{font-size:12px}.info-bar .placeholder{text-align:center;color:var(--color-grey-300)}.info-bar .preview img{max-width:100%}.info-bar .details{font-size:12px;word-break:break-all}.info-bar .name{line-height:14px;font-weight:700}\n"] }]
12002
- }], ctorParameters: function () { return [{ type: ModalService }]; }, propDecorators: { assets: [{
12003
- type: Input
12004
- }], multiSelect: [{
12005
- type: Input
12006
- }], canDelete: [{
12007
- type: Input
12008
- }], selectionChange: [{
12009
- type: Output
12010
- }], deleteAssets: [{
12011
- type: Output
12012
- }] } });
12013
-
12014
- /**
12015
- * A control for setting the number of items per page in a paginated list.
12016
- */
12017
- class ItemsPerPageControlsComponent {
12018
- constructor() {
12019
- this.itemsPerPage = 10;
12020
- this.itemsPerPageChange = new EventEmitter();
12609
+ .subscribe();
12021
12610
  }
12022
- }
12023
- ItemsPerPageControlsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ItemsPerPageControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12024
- ItemsPerPageControlsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ItemsPerPageControlsComponent, selector: "vdr-items-per-page-controls", inputs: { itemsPerPage: "itemsPerPage" }, outputs: { itemsPerPageChange: "itemsPerPageChange" }, ngImport: i0, template: "<div class=\"select\">\r\n <select [ngModel]=\"itemsPerPage\" (change)=\"itemsPerPageChange.emit($event.target.value)\">\r\n <option [value]=\"10\">{{ 'common.items-per-page-option' | translate: { count: 10 } }}</option>\r\n <option [value]=\"25\">{{ 'common.items-per-page-option' | translate: { count: 25 } }}</option>\r\n <option [value]=\"50\">{{ 'common.items-per-page-option' | translate: { count: 50 } }}</option>\r\n <option [value]=\"100\">{{ 'common.items-per-page-option' | translate: { count: 100 } }}</option>\r\n </select>\r\n</div>\r\n", styles: [""], directives: [{ type: FormFieldControlDirective, selector: "input, textarea, select" }, { type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }], pipes: { "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
12025
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ItemsPerPageControlsComponent, decorators: [{
12026
- type: Component,
12027
- args: [{ selector: 'vdr-items-per-page-controls', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"select\">\r\n <select [ngModel]=\"itemsPerPage\" (change)=\"itemsPerPageChange.emit($event.target.value)\">\r\n <option [value]=\"10\">{{ 'common.items-per-page-option' | translate: { count: 10 } }}</option>\r\n <option [value]=\"25\">{{ 'common.items-per-page-option' | translate: { count: 25 } }}</option>\r\n <option [value]=\"50\">{{ 'common.items-per-page-option' | translate: { count: 50 } }}</option>\r\n <option [value]=\"100\">{{ 'common.items-per-page-option' | translate: { count: 100 } }}</option>\r\n </select>\r\n</div>\r\n", styles: [""] }]
12028
- }], propDecorators: { itemsPerPage: [{
12029
- type: Input
12030
- }], itemsPerPageChange: [{
12031
- type: Output
12032
- }] } });
12033
-
12034
- class PaginationControlsComponent {
12035
- constructor() {
12036
- this.pageChange = new EventEmitter();
12611
+ entityInfoClick(event) {
12612
+ event.preventDefault();
12613
+ event.stopPropagation();
12037
12614
  }
12038
12615
  }
12039
- PaginationControlsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: PaginationControlsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
12040
- PaginationControlsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: PaginationControlsComponent, selector: "vdr-pagination-controls", inputs: { id: "id", currentPage: "currentPage", itemsPerPage: "itemsPerPage", totalItems: "totalItems" }, outputs: { pageChange: "pageChange" }, ngImport: i0, template: "<pagination-template #p=\"paginationApi\" (pageChange)=\"pageChange.emit($event)\" [id]=\"id\">\r\n <ul>\r\n <li class=\"pagination-previous\">\r\n <a *ngIf=\"!p.isFirstPage()\" (click)=\"p.previous()\" (keyup.enter)=\"p.previous()\" tabindex=\"0\">\u00AB</a>\r\n <div *ngIf=\"p.isFirstPage()\">\u00AB</div>\r\n </li>\r\n\r\n <li *ngFor=\"let page of p.pages\">\r\n <a\r\n (click)=\"p.setCurrent(page.value)\"\r\n (keyup.enter)=\"p.setCurrent(page.value)\"\r\n *ngIf=\"p.getCurrent() !== page.value\"\r\n tabindex=\"0\"\r\n >\r\n {{ page.label }}\r\n </a>\r\n\r\n <div class=\"current\" *ngIf=\"p.getCurrent() === page.value\">{{ page.label }}</div>\r\n </li>\r\n\r\n <li class=\"pagination-next\">\r\n <a *ngIf=\"!p.isLastPage()\" (click)=\"p.next()\" (keyup.enter)=\"p.next()\" tabindex=\"0\">\u00BB</a>\r\n <div *ngIf=\"p.isLastPage()\">\u00BB</div>\r\n </li>\r\n </ul>\r\n</pagination-template>\r\n", styles: ["pagination-template{display:block}pagination-template ul{list-style-type:none;display:flex;justify-content:center}pagination-template li{transition:border-bottom-color .2s}pagination-template li>a{cursor:pointer}pagination-template li>a:hover,pagination-template li>a:focus{border-bottom-color:var(--color-grey-300);text-decoration:none}pagination-template li>a,pagination-template li>div{padding:3px 12px;display:block;border-bottom:3px solid transparent;-webkit-user-select:none;user-select:none}pagination-template li>div.current{border-bottom-color:var(--color-primary-500)}\n"], directives: [{ type: i1$5.PaginationControlsDirective, selector: "pagination-template,[pagination-template]", inputs: ["maxSize", "id"], outputs: ["pageChange", "pageBoundsCorrection"], exportAs: ["paginationApi"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
12041
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: PaginationControlsComponent, decorators: [{
12616
+ AssetGalleryComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetGalleryComponent, deps: [{ token: ModalService }], target: i0.ɵɵFactoryTarget.Component });
12617
+ AssetGalleryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: AssetGalleryComponent, selector: "vdr-asset-gallery", inputs: { assets: "assets", multiSelect: "multiSelect", canDelete: "canDelete" }, outputs: { selectionChange: "selectionChange", deleteAssets: "deleteAssets" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"gallery\">\r\n <div\r\n class=\"card\"\r\n *ngFor=\"let asset of assets\"\r\n (click)=\"toggleSelection(asset, $event)\"\r\n [class.selected]=\"isSelected(asset)\"\r\n >\r\n <div class=\"card-img\">\r\n <vdr-select-toggle\r\n [selected]=\"isSelected(asset)\"\r\n [disabled]=\"true\"\r\n [hiddenWhenOff]=\"true\"\r\n ></vdr-select-toggle>\r\n <img class=\"asset-thumb\" [src]=\"asset | assetPreview: 'thumb'\" />\r\n </div>\r\n <div class=\"detail\">\r\n <vdr-entity-info\r\n [entity]=\"asset\"\r\n [small]=\"true\"\r\n (click)=\"entityInfoClick($event)\"\r\n ></vdr-entity-info>\r\n <span [title]=\"asset.name\">{{ asset.name }}</span>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"info-bar\">\r\n <div class=\"card\">\r\n <div class=\"card-img\">\r\n <div class=\"placeholder\" *ngIf=\"selectionManager.selection.length === 0\">\r\n <clr-icon shape=\"image\" size=\"128\"></clr-icon>\r\n <div>{{ 'catalog.no-selection' | translate }}</div>\r\n </div>\r\n <img\r\n class=\"preview\"\r\n *ngIf=\"selectionManager.selection.length >= 1\"\r\n [src]=\"lastSelected().preview + '?preset=medium'\"\r\n />\r\n </div>\r\n <div class=\"card-block details\" *ngIf=\"selectionManager.selection.length >= 1\">\r\n <div class=\"name\">{{ lastSelected().name }}</div>\r\n <div>{{ 'asset.original-asset-size' | translate }}: {{ lastSelected().fileSize | filesize }}</div>\r\n\r\n <ng-container *ngIf=\"selectionManager.selection.length === 1\">\r\n <vdr-chip *ngFor=\"let tag of lastSelected().tags\" [colorFrom]=\"tag.value\"\r\n ><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag.value }}</vdr-chip\r\n >\r\n <div>\r\n <button (click)=\"previewAsset(lastSelected())\" class=\"btn btn-link\">\r\n <clr-icon shape=\"eye\"></clr-icon> {{ 'asset.preview' | translate }}\r\n </button>\r\n </div>\r\n <div>\r\n <vdr-asset-preview-links class=\"\" [asset]=\"lastSelected()\"></vdr-asset-preview-links>\r\n </div>\r\n <div>\r\n <a [routerLink]=\"['./', lastSelected().id]\" class=\"btn btn-link\">\r\n <clr-icon shape=\"pencil\"></clr-icon> {{ 'common.edit' | translate }}\r\n </a>\r\n </div>\r\n </ng-container>\r\n <div *ngIf=\"canDelete\">\r\n <button (click)=\"deleteAssets.emit(selectionManager.selection)\" class=\"btn btn-link\">\r\n <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon> {{ 'common.delete' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card stack\" [class.visible]=\"selectionManager.selection.length > 1\"></div>\r\n <div class=\"selection-count\" [class.visible]=\"selectionManager.selection.length > 1\">\r\n {{ 'asset.assets-selected-count' | translate: { count: selectionManager.selection.length } }}\r\n <ul>\r\n <li *ngFor=\"let asset of selectionManager.selection\">{{ asset.name }}</li>\r\n </ul>\r\n </div>\r\n</div>\r\n", styles: [":host{display:flex;overflow:hidden}.gallery{flex:1;display:grid;grid-template-columns:repeat(auto-fill,150px);grid-template-rows:repeat(auto-fill,180px);grid-gap:10px 20px;overflow-y:auto;padding-left:12px;padding-top:12px;padding-bottom:12px}.gallery .card:hover{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.card{margin-top:0;position:relative}img.asset-thumb{aspect-ratio:1}vdr-select-toggle{position:absolute;top:-12px;left:-12px}vdr-select-toggle ::ng-deep .toggle{box-shadow:0 5px 5px -4px #000000bf}.card.selected{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.card.selected .selected-checkbox{opacity:1}.detail{font-size:12px;margin:3px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.detail vdr-entity-info{height:16px}.info-bar{width:25%;padding:0 6px;overflow-y:auto}.info-bar .card{z-index:1}.info-bar .stack{z-index:0;opacity:0;transform:perspective(500px) translateZ(0) translateY(-16px);height:16px;transition:transform .3s,opacity 0s .3s;background-color:#fff}.info-bar .stack.visible{opacity:1;transform:perspective(500px) translateZ(-44px) translateY(0);background-color:var(--color-component-bg-100);transition:transform .3s,color .3s}.info-bar .selection-count{opacity:0;position:relative;text-align:center;visibility:hidden;transition:opacity .3s,visibility 0s .3s}.info-bar .selection-count.visible{opacity:1;visibility:visible;transition:opacity .3s,visibility 0s}.info-bar .selection-count ul{text-align:left;list-style-type:none;margin-left:12px}.info-bar .selection-count ul li{font-size:12px}.info-bar .placeholder{text-align:center;color:var(--color-grey-300)}.info-bar .preview img{max-width:100%}.info-bar .details{font-size:12px;word-break:break-all}.info-bar .name{line-height:14px;font-weight:700}\n"], components: [{ type: SelectToggleComponent, selector: "vdr-select-toggle", inputs: ["size", "selected", "hiddenWhenOff", "disabled", "label"], outputs: ["selectedChange"] }, { type: EntityInfoComponent, selector: "vdr-entity-info", inputs: ["small", "entity"] }, { type: ChipComponent, selector: "vdr-chip", inputs: ["icon", "invert", "colorFrom", "colorType"], outputs: ["iconClick"] }, { type: AssetPreviewLinksComponent, selector: "vdr-asset-preview-links", inputs: ["asset"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i1$2.RouterLinkWithHref, selector: "a[routerLink],area[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "preserveFragment", "skipLocationChange", "replaceUrl", "state", "relativeTo", "routerLink"] }], pipes: { "assetPreview": AssetPreviewPipe, "translate": i7.TranslatePipe, "filesize": FileSizePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
12618
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: AssetGalleryComponent, decorators: [{
12042
12619
  type: Component,
12043
- args: [{ selector: 'vdr-pagination-controls', changeDetection: ChangeDetectionStrategy.OnPush, template: "<pagination-template #p=\"paginationApi\" (pageChange)=\"pageChange.emit($event)\" [id]=\"id\">\r\n <ul>\r\n <li class=\"pagination-previous\">\r\n <a *ngIf=\"!p.isFirstPage()\" (click)=\"p.previous()\" (keyup.enter)=\"p.previous()\" tabindex=\"0\">\u00AB</a>\r\n <div *ngIf=\"p.isFirstPage()\">\u00AB</div>\r\n </li>\r\n\r\n <li *ngFor=\"let page of p.pages\">\r\n <a\r\n (click)=\"p.setCurrent(page.value)\"\r\n (keyup.enter)=\"p.setCurrent(page.value)\"\r\n *ngIf=\"p.getCurrent() !== page.value\"\r\n tabindex=\"0\"\r\n >\r\n {{ page.label }}\r\n </a>\r\n\r\n <div class=\"current\" *ngIf=\"p.getCurrent() === page.value\">{{ page.label }}</div>\r\n </li>\r\n\r\n <li class=\"pagination-next\">\r\n <a *ngIf=\"!p.isLastPage()\" (click)=\"p.next()\" (keyup.enter)=\"p.next()\" tabindex=\"0\">\u00BB</a>\r\n <div *ngIf=\"p.isLastPage()\">\u00BB</div>\r\n </li>\r\n </ul>\r\n</pagination-template>\r\n", styles: ["pagination-template{display:block}pagination-template ul{list-style-type:none;display:flex;justify-content:center}pagination-template li{transition:border-bottom-color .2s}pagination-template li>a{cursor:pointer}pagination-template li>a:hover,pagination-template li>a:focus{border-bottom-color:var(--color-grey-300);text-decoration:none}pagination-template li>a,pagination-template li>div{padding:3px 12px;display:block;border-bottom:3px solid transparent;-webkit-user-select:none;user-select:none}pagination-template li>div.current{border-bottom-color:var(--color-primary-500)}\n"] }]
12044
- }], propDecorators: { id: [{
12045
- type: Input
12046
- }], currentPage: [{
12620
+ args: [{ selector: 'vdr-asset-gallery', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gallery\">\r\n <div\r\n class=\"card\"\r\n *ngFor=\"let asset of assets\"\r\n (click)=\"toggleSelection(asset, $event)\"\r\n [class.selected]=\"isSelected(asset)\"\r\n >\r\n <div class=\"card-img\">\r\n <vdr-select-toggle\r\n [selected]=\"isSelected(asset)\"\r\n [disabled]=\"true\"\r\n [hiddenWhenOff]=\"true\"\r\n ></vdr-select-toggle>\r\n <img class=\"asset-thumb\" [src]=\"asset | assetPreview: 'thumb'\" />\r\n </div>\r\n <div class=\"detail\">\r\n <vdr-entity-info\r\n [entity]=\"asset\"\r\n [small]=\"true\"\r\n (click)=\"entityInfoClick($event)\"\r\n ></vdr-entity-info>\r\n <span [title]=\"asset.name\">{{ asset.name }}</span>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"info-bar\">\r\n <div class=\"card\">\r\n <div class=\"card-img\">\r\n <div class=\"placeholder\" *ngIf=\"selectionManager.selection.length === 0\">\r\n <clr-icon shape=\"image\" size=\"128\"></clr-icon>\r\n <div>{{ 'catalog.no-selection' | translate }}</div>\r\n </div>\r\n <img\r\n class=\"preview\"\r\n *ngIf=\"selectionManager.selection.length >= 1\"\r\n [src]=\"lastSelected().preview + '?preset=medium'\"\r\n />\r\n </div>\r\n <div class=\"card-block details\" *ngIf=\"selectionManager.selection.length >= 1\">\r\n <div class=\"name\">{{ lastSelected().name }}</div>\r\n <div>{{ 'asset.original-asset-size' | translate }}: {{ lastSelected().fileSize | filesize }}</div>\r\n\r\n <ng-container *ngIf=\"selectionManager.selection.length === 1\">\r\n <vdr-chip *ngFor=\"let tag of lastSelected().tags\" [colorFrom]=\"tag.value\"\r\n ><clr-icon shape=\"tag\" class=\"mr2\"></clr-icon> {{ tag.value }}</vdr-chip\r\n >\r\n <div>\r\n <button (click)=\"previewAsset(lastSelected())\" class=\"btn btn-link\">\r\n <clr-icon shape=\"eye\"></clr-icon> {{ 'asset.preview' | translate }}\r\n </button>\r\n </div>\r\n <div>\r\n <vdr-asset-preview-links class=\"\" [asset]=\"lastSelected()\"></vdr-asset-preview-links>\r\n </div>\r\n <div>\r\n <a [routerLink]=\"['./', lastSelected().id]\" class=\"btn btn-link\">\r\n <clr-icon shape=\"pencil\"></clr-icon> {{ 'common.edit' | translate }}\r\n </a>\r\n </div>\r\n </ng-container>\r\n <div *ngIf=\"canDelete\">\r\n <button (click)=\"deleteAssets.emit(selectionManager.selection)\" class=\"btn btn-link\">\r\n <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon> {{ 'common.delete' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"card stack\" [class.visible]=\"selectionManager.selection.length > 1\"></div>\r\n <div class=\"selection-count\" [class.visible]=\"selectionManager.selection.length > 1\">\r\n {{ 'asset.assets-selected-count' | translate: { count: selectionManager.selection.length } }}\r\n <ul>\r\n <li *ngFor=\"let asset of selectionManager.selection\">{{ asset.name }}</li>\r\n </ul>\r\n </div>\r\n</div>\r\n", styles: [":host{display:flex;overflow:hidden}.gallery{flex:1;display:grid;grid-template-columns:repeat(auto-fill,150px);grid-template-rows:repeat(auto-fill,180px);grid-gap:10px 20px;overflow-y:auto;padding-left:12px;padding-top:12px;padding-bottom:12px}.gallery .card:hover{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.card{margin-top:0;position:relative}img.asset-thumb{aspect-ratio:1}vdr-select-toggle{position:absolute;top:-12px;left:-12px}vdr-select-toggle ::ng-deep .toggle{box-shadow:0 5px 5px -4px #000000bf}.card.selected{box-shadow:0 .125rem 0 0 var(--color-primary-500);border:1px solid var(--color-primary-500)}.card.selected .selected-checkbox{opacity:1}.detail{font-size:12px;margin:3px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.detail vdr-entity-info{height:16px}.info-bar{width:25%;padding:0 6px;overflow-y:auto}.info-bar .card{z-index:1}.info-bar .stack{z-index:0;opacity:0;transform:perspective(500px) translateZ(0) translateY(-16px);height:16px;transition:transform .3s,opacity 0s .3s;background-color:#fff}.info-bar .stack.visible{opacity:1;transform:perspective(500px) translateZ(-44px) translateY(0);background-color:var(--color-component-bg-100);transition:transform .3s,color .3s}.info-bar .selection-count{opacity:0;position:relative;text-align:center;visibility:hidden;transition:opacity .3s,visibility 0s .3s}.info-bar .selection-count.visible{opacity:1;visibility:visible;transition:opacity .3s,visibility 0s}.info-bar .selection-count ul{text-align:left;list-style-type:none;margin-left:12px}.info-bar .selection-count ul li{font-size:12px}.info-bar .placeholder{text-align:center;color:var(--color-grey-300)}.info-bar .preview img{max-width:100%}.info-bar .details{font-size:12px;word-break:break-all}.info-bar .name{line-height:14px;font-weight:700}\n"] }]
12621
+ }], ctorParameters: function () { return [{ type: ModalService }]; }, propDecorators: { assets: [{
12047
12622
  type: Input
12048
- }], itemsPerPage: [{
12623
+ }], multiSelect: [{
12049
12624
  type: Input
12050
- }], totalItems: [{
12625
+ }], canDelete: [{
12051
12626
  type: Input
12052
- }], pageChange: [{
12627
+ }], selectionChange: [{
12628
+ type: Output
12629
+ }], deleteAssets: [{
12053
12630
  type: Output
12054
12631
  }] } });
12055
12632
 
@@ -12240,7 +12817,7 @@ class RelationAssetInputComponent {
12240
12817
  this.dataService = dataService;
12241
12818
  }
12242
12819
  ngOnInit() {
12243
- this.asset$ = this.parentFormControl.valueChanges.pipe(startWith(this.parentFormControl.value), map(asset => asset === null || asset === void 0 ? void 0 : asset.id), distinctUntilChanged(), switchMap(id => {
12820
+ this.asset$ = this.formControl.valueChanges.pipe(startWith(this.formControl.value), map(asset => asset === null || asset === void 0 ? void 0 : asset.id), distinctUntilChanged(), switchMap(id => {
12244
12821
  if (id) {
12245
12822
  return this.dataService.product.getAsset(id).mapStream(data => data.asset || undefined);
12246
12823
  }
@@ -12259,14 +12836,14 @@ class RelationAssetInputComponent {
12259
12836
  })
12260
12837
  .subscribe(result => {
12261
12838
  if (result && result.length) {
12262
- this.parentFormControl.setValue(result[0]);
12263
- this.parentFormControl.markAsDirty();
12839
+ this.formControl.setValue(result[0]);
12840
+ this.formControl.markAsDirty();
12264
12841
  }
12265
12842
  });
12266
12843
  }
12267
12844
  remove() {
12268
- this.parentFormControl.setValue(null);
12269
- this.parentFormControl.markAsDirty();
12845
+ this.formControl.setValue(null);
12846
+ this.formControl.markAsDirty();
12270
12847
  }
12271
12848
  previewAsset(asset) {
12272
12849
  this.modalService
@@ -12278,15 +12855,17 @@ class RelationAssetInputComponent {
12278
12855
  .subscribe();
12279
12856
  }
12280
12857
  }
12858
+ RelationAssetInputComponent.id = 'asset-form-input';
12281
12859
  RelationAssetInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: RelationAssetInputComponent, deps: [{ token: ModalService }, { token: DataService }], target: i0.ɵɵFactoryTarget.Component });
12282
- RelationAssetInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: RelationAssetInputComponent, selector: "vdr-relation-asset-input", inputs: { readonly: "readonly", parentFormControl: "parentFormControl", config: "config" }, ngImport: i0, template: "<vdr-relation-card\r\n (select)=\"selectAsset()\"\r\n (remove)=\"remove()\"\r\n placeholderIcon=\"image\"\r\n [entity]=\"asset$ | async\"\r\n [selectLabel]=\"'asset.select-asset' | translate\"\r\n [removable]=\"!config.list\"\r\n [readonly]=\"readonly\"\r\n>\r\n <ng-template vdrRelationCardPreview let-asset=\"entity\">\r\n <img\r\n class=\"preview\"\r\n [title]=\"'asset.preview' | translate\"\r\n [src]=\"asset | assetPreview: 'tiny'\"\r\n (click)=\"previewAsset(asset)\"\r\n />\r\n </ng-template>\r\n <ng-template vdrRelationCardDetail let-asset=\"entity\">\r\n <div class=\"name\" [title]=\"asset.name\">\r\n {{ asset.name }}\r\n </div>\r\n </ng-template>\r\n</vdr-relation-card>\r\n", styles: [".preview{cursor:pointer}.detail{flex:1;overflow:hidden}.name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], components: [{ type: RelationCardComponent, selector: "vdr-relation-card", inputs: ["entity", "placeholderIcon", "selectLabel", "readonly", "removable"], outputs: ["select", "remove"] }], directives: [{ type: RelationCardPreviewDirective, selector: "[vdrRelationCardPreview]" }, { type: RelationCardDetailDirective, selector: "[vdrRelationCardDetail]" }], pipes: { "async": i3.AsyncPipe, "translate": i7.TranslatePipe, "assetPreview": AssetPreviewPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
12860
+ RelationAssetInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: RelationAssetInputComponent, selector: "vdr-relation-asset-input", inputs: { readonly: "readonly", formControl: ["parentFormControl", "formControl"], config: "config" }, ngImport: i0, template: "<vdr-relation-card\r\n (select)=\"selectAsset()\"\r\n (remove)=\"remove()\"\r\n placeholderIcon=\"image\"\r\n [entity]=\"asset$ | async\"\r\n [selectLabel]=\"'asset.select-asset' | translate\"\r\n [removable]=\"!config.list\"\r\n [readonly]=\"readonly\"\r\n>\r\n <ng-template vdrRelationCardPreview let-asset=\"entity\">\r\n <img\r\n class=\"preview\"\r\n [title]=\"'asset.preview' | translate\"\r\n [src]=\"asset | assetPreview: 'tiny'\"\r\n (click)=\"previewAsset(asset)\"\r\n />\r\n </ng-template>\r\n <ng-template vdrRelationCardDetail let-asset=\"entity\">\r\n <div class=\"name\" [title]=\"asset.name\">\r\n {{ asset.name }}\r\n </div>\r\n </ng-template>\r\n</vdr-relation-card>\r\n", styles: [".preview{cursor:pointer}.detail{flex:1;overflow:hidden}.name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], components: [{ type: RelationCardComponent, selector: "vdr-relation-card", inputs: ["entity", "placeholderIcon", "selectLabel", "readonly", "removable"], outputs: ["select", "remove"] }], directives: [{ type: RelationCardPreviewDirective, selector: "[vdrRelationCardPreview]" }, { type: RelationCardDetailDirective, selector: "[vdrRelationCardDetail]" }], pipes: { "async": i3.AsyncPipe, "translate": i7.TranslatePipe, "assetPreview": AssetPreviewPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
12283
12861
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: RelationAssetInputComponent, decorators: [{
12284
12862
  type: Component,
12285
12863
  args: [{ selector: 'vdr-relation-asset-input', changeDetection: ChangeDetectionStrategy.OnPush, template: "<vdr-relation-card\r\n (select)=\"selectAsset()\"\r\n (remove)=\"remove()\"\r\n placeholderIcon=\"image\"\r\n [entity]=\"asset$ | async\"\r\n [selectLabel]=\"'asset.select-asset' | translate\"\r\n [removable]=\"!config.list\"\r\n [readonly]=\"readonly\"\r\n>\r\n <ng-template vdrRelationCardPreview let-asset=\"entity\">\r\n <img\r\n class=\"preview\"\r\n [title]=\"'asset.preview' | translate\"\r\n [src]=\"asset | assetPreview: 'tiny'\"\r\n (click)=\"previewAsset(asset)\"\r\n />\r\n </ng-template>\r\n <ng-template vdrRelationCardDetail let-asset=\"entity\">\r\n <div class=\"name\" [title]=\"asset.name\">\r\n {{ asset.name }}\r\n </div>\r\n </ng-template>\r\n</vdr-relation-card>\r\n", styles: [".preview{cursor:pointer}.detail{flex:1;overflow:hidden}.name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
12286
12864
  }], ctorParameters: function () { return [{ type: ModalService }, { type: DataService }]; }, propDecorators: { readonly: [{
12287
12865
  type: Input
12288
- }], parentFormControl: [{
12289
- type: Input
12866
+ }], formControl: [{
12867
+ type: Input,
12868
+ args: ['parentFormControl']
12290
12869
  }], config: [{
12291
12870
  type: Input
12292
12871
  }] } });
@@ -13344,7 +13923,7 @@ RichTextEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0"
13344
13923
  multi: true,
13345
13924
  },
13346
13925
  ProsemirrorService,
13347
- ], viewQueries: [{ propertyName: "editorEl", first: true, predicate: ["editor"], descendants: true, static: true }], ngImport: i0, template: "<label class=\"clr-control-label\">{{ label }}</label>\r\n<div #editor></div>\r\n", styles: ["@charset \"UTF-8\";::ng-deep .ProseMirror{position:relative}::ng-deep .ProseMirror{word-wrap:break-word;white-space:pre-wrap;-webkit-font-variant-ligatures:none;font-feature-settings:none;font-variant-ligatures:none}::ng-deep .ProseMirror pre{white-space:pre-wrap}::ng-deep .ProseMirror li{position:relative}::ng-deep .ProseMirror-hideselection *::selection{background:transparent}::ng-deep .ProseMirror-hideselection *::-moz-selection{background:transparent}::ng-deep .ProseMirror-hideselection{caret-color:transparent}::ng-deep .ProseMirror-selectednode{outline:2px solid var(--color-primary-500)}::ng-deep li.ProseMirror-selectednode{outline:none}::ng-deep li.ProseMirror-selectednode:after{content:\"\";position:absolute;left:-32px;right:-2px;top:-2px;bottom:-2px;border:2px solid var(--color-primary-500);pointer-events:none}::ng-deep .ProseMirror-textblock-dropdown{min-width:3em}::ng-deep .ProseMirror-menu{margin:0 -4px;line-height:1}::ng-deep .ProseMirror-tooltip .ProseMirror-menu{width:-moz-fit-content;width:fit-content;white-space:pre}::ng-deep .ProseMirror-menuitem{margin-right:3px;display:inline-block}::ng-deep .ProseMirror-menuseparator{border-right:1px solid var(--color-component-border-200);margin-right:3px}::ng-deep .ProseMirror-menu-dropdown,::ng-deep .ProseMirror-menu-dropdown-menu{font-size:90%;white-space:nowrap}::ng-deep .ProseMirror-menu-dropdown{vertical-align:1px;cursor:pointer;position:relative;padding-right:15px}::ng-deep .ProseMirror-menu-dropdown-wrap{padding:1px 0 1px 4px;display:inline-block;position:relative}::ng-deep .ProseMirror-menu-dropdown:after{content:\"\";border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid currentColor;opacity:.6;position:absolute;right:4px;top:calc(50% - 2px)}::ng-deep .ProseMirror-menu-dropdown-menu,::ng-deep .ProseMirror-menu-submenu{position:absolute;background:white;color:var(--color-grey-600);border:1px solid var(--color-component-border-200);padding:2px}::ng-deep .ProseMirror-menu-dropdown-menu{z-index:15;min-width:6em}::ng-deep .ProseMirror-menu-dropdown-item{cursor:pointer;padding:2px 8px 2px 4px}::ng-deep .ProseMirror-menu-dropdown-item:hover{background:var(--color-component-bg-100)}::ng-deep .ProseMirror-menu-submenu-wrap{position:relative;margin-right:-4px}::ng-deep .ProseMirror-menu-submenu-label:after{content:\"\";border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid currentColor;opacity:.6;position:absolute;right:4px;top:calc(50% - 4px)}::ng-deep .ProseMirror-menu-submenu{display:none;min-width:4em;left:100%;top:-3px}::ng-deep .ProseMirror-menu-active{background:var(--color-component-bg-100);border-radius:4px}::ng-deep .ProseMirror-menu-disabled{opacity:.3}::ng-deep .ProseMirror-menu-submenu-wrap:hover .ProseMirror-menu-submenu,::ng-deep .ProseMirror-menu-submenu-wrap-active .ProseMirror-menu-submenu{display:block}::ng-deep .ProseMirror-menubar{border-top-left-radius:inherit;border-top-right-radius:inherit;position:relative;min-height:1em;color:var(--color-grey-600);padding:1px 6px;top:0;left:0;right:0;background:var(--color-component-bg-100);z-index:10;box-sizing:border-box;overflow:visible}::ng-deep .ProseMirror-icon{display:inline-block;line-height:.8;vertical-align:-2px;padding:2px 8px;cursor:pointer}::ng-deep .ProseMirror-menu-disabled.ProseMirror-icon{cursor:default}::ng-deep .ProseMirror-icon svg{fill:currentColor;height:1em}::ng-deep .ProseMirror-icon span{vertical-align:text-top}::ng-deep .ProseMirror-gapcursor{display:none;pointer-events:none;position:absolute}::ng-deep .ProseMirror-gapcursor:after{content:\"\";display:block;position:absolute;top:-2px;width:20px;border-top:1px solid black;animation:ProseMirror-cursor-blink 1.1s steps(2,start) infinite}@keyframes ProseMirror-cursor-blink{to{visibility:hidden}}::ng-deep .ProseMirror-focused .ProseMirror-gapcursor{display:block}::ng-deep .ProseMirror ul,::ng-deep .ProseMirror ol{padding-left:30px;list-style-position:initial}::ng-deep .ProseMirror blockquote{padding-left:1em;border-left:3px solid var(--color-grey-100);margin-left:0;margin-right:0}::ng-deep .ProseMirror-prompt{background:white;padding:5px 10px 5px 15px;border:1px solid silver;position:fixed;border-radius:3px;z-index:11;box-shadow:-.5px 2px 5px #0003}::ng-deep .ProseMirror-prompt h5{margin:0;font-weight:400;font-size:100%;color:var(--color-grey-500)}::ng-deep .ProseMirror-prompt input[type=text],::ng-deep .ProseMirror-prompt textarea{background:var(--color-component-bg-100);border:none;outline:none}::ng-deep .ProseMirror-prompt input[type=text]{padding:0 4px}::ng-deep .ProseMirror-prompt-close{position:absolute;left:2px;top:1px;color:var(--color-grey-400);border:none;background:transparent;padding:0}::ng-deep .ProseMirror-prompt-close:after{content:\"\\e2\\153\\2022\";font-size:12px}::ng-deep .ProseMirror-invalid{background:var(--color-warning-200);border:1px solid var(--color-warning-300);border-radius:4px;padding:5px 10px;position:absolute;min-width:10em}::ng-deep .ProseMirror-prompt-buttons{margin-top:5px;display:none}::ng-deep #editor,::ng-deep .editor{background:var(--color-form-input-bg);color:#000;background-clip:padding-box;border-radius:4px;border:2px solid rgba(0,0,0,.2);padding:5px 0;margin-bottom:23px}::ng-deep .ProseMirror p:first-child,::ng-deep .ProseMirror h1:first-child,::ng-deep .ProseMirror h2:first-child,::ng-deep .ProseMirror h3:first-child,::ng-deep .ProseMirror h4:first-child,::ng-deep .ProseMirror h5:first-child,::ng-deep .ProseMirror h6:first-child{margin-top:10px}::ng-deep .ProseMirror{padding:4px 8px 4px 14px;line-height:1.2;outline:none}::ng-deep .ProseMirror p{margin-bottom:.5rem;color:var(--color-grey-800)!important}:host{display:block;max-width:710px;margin-bottom:.5rem}:host.readonly ::ng-deep .ProseMirror-menubar{display:none}::ng-deep .ProseMirror-menubar{position:sticky;top:24px;margin-top:6px;border:1px solid var(--color-component-border-200);border-bottom:none;background-color:var(--color-component-bg-200);color:var(--color-icon-button);padding:6px 12px;display:flex;flex-wrap:wrap}::ng-deep .vdr-prosemirror{background:var(--color-form-input-bg);min-height:128px;min-width:200px;border:1px solid var(--color-component-border-200);border-radius:0 0 3px 3px;transition:border-color .2s;overflow:auto;text-align:initial}::ng-deep .vdr-prosemirror:focus{border-color:var(--color-primary-500)!important;box-shadow:0 0 1px 1px var(--color-primary-100)}::ng-deep .vdr-prosemirror hr{padding:2px 10px;border:none;margin:1em 0}::ng-deep .vdr-prosemirror hr:after{content:\"\";display:block;height:1px;background-color:silver;line-height:2px}::ng-deep .vdr-prosemirror img{cursor:default;max-width:100%}\n"], directives: [{ type: i1$3.ClrLabel, selector: "label", inputs: ["for"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13926
+ ], viewQueries: [{ propertyName: "editorEl", first: true, predicate: ["editor"], descendants: true, static: true }], ngImport: i0, template: "<label class=\"clr-control-label\">{{ label }}</label>\r\n<div #editor></div>\r\n", styles: ["@charset \"UTF-8\";::ng-deep .ProseMirror{position:relative}::ng-deep .ProseMirror{word-wrap:break-word;white-space:pre-wrap;-webkit-font-variant-ligatures:none;font-feature-settings:none;font-variant-ligatures:none}::ng-deep .ProseMirror pre{white-space:pre-wrap}::ng-deep .ProseMirror li{position:relative}::ng-deep .ProseMirror-hideselection *::selection{background:transparent}::ng-deep .ProseMirror-hideselection *::-moz-selection{background:transparent}::ng-deep .ProseMirror-hideselection{caret-color:transparent}::ng-deep .ProseMirror-selectednode{outline:2px solid var(--color-primary-500)}::ng-deep li.ProseMirror-selectednode{outline:none}::ng-deep li.ProseMirror-selectednode:after{content:\"\";position:absolute;left:-32px;right:-2px;top:-2px;bottom:-2px;border:2px solid var(--color-primary-500);pointer-events:none}::ng-deep .ProseMirror-textblock-dropdown{min-width:3em}::ng-deep .ProseMirror-menu{margin:0 -4px;line-height:1}::ng-deep .ProseMirror-tooltip .ProseMirror-menu{width:-moz-fit-content;width:fit-content;white-space:pre}::ng-deep .ProseMirror-menuitem{margin-right:3px;display:inline-block}::ng-deep .ProseMirror-menuseparator{border-right:1px solid var(--color-component-border-200);margin-right:3px}::ng-deep .ProseMirror-menu-dropdown,::ng-deep .ProseMirror-menu-dropdown-menu{font-size:90%;white-space:nowrap}::ng-deep .ProseMirror-menu-dropdown{vertical-align:1px;cursor:pointer;position:relative;padding-right:15px}::ng-deep .ProseMirror-menu-dropdown-wrap{padding:1px 0 1px 4px;display:inline-block;position:relative}::ng-deep .ProseMirror-menu-dropdown:after{content:\"\";border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid currentColor;opacity:.6;position:absolute;right:4px;top:calc(50% - 2px)}::ng-deep .ProseMirror-menu-dropdown-menu,::ng-deep .ProseMirror-menu-submenu{position:absolute;background:white;color:var(--color-grey-600);border:1px solid var(--color-component-border-200);padding:2px}::ng-deep .ProseMirror-menu-dropdown-menu{z-index:15;min-width:6em}::ng-deep .ProseMirror-menu-dropdown-item{cursor:pointer;padding:2px 8px 2px 4px}::ng-deep .ProseMirror-menu-dropdown-item:hover{background:var(--color-component-bg-100)}::ng-deep .ProseMirror-menu-submenu-wrap{position:relative;margin-right:-4px}::ng-deep .ProseMirror-menu-submenu-label:after{content:\"\";border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid currentColor;opacity:.6;position:absolute;right:4px;top:calc(50% - 4px)}::ng-deep .ProseMirror-menu-submenu{display:none;min-width:4em;left:100%;top:-3px}::ng-deep .ProseMirror-menu-active{background:var(--color-component-bg-100);border-radius:4px}::ng-deep .ProseMirror-menu-disabled{opacity:.3}::ng-deep .ProseMirror-menu-submenu-wrap:hover .ProseMirror-menu-submenu,::ng-deep .ProseMirror-menu-submenu-wrap-active .ProseMirror-menu-submenu{display:block}::ng-deep .ProseMirror-menubar{border-top-left-radius:inherit;border-top-right-radius:inherit;position:relative;min-height:1em;color:var(--color-grey-600);padding:1px 6px;top:0;left:0;right:0;background:var(--color-component-bg-100);z-index:10;box-sizing:border-box;overflow:visible}::ng-deep .ProseMirror-icon{display:inline-block;line-height:.8;vertical-align:-2px;padding:2px 8px;cursor:pointer}::ng-deep .ProseMirror-menu-disabled.ProseMirror-icon{cursor:default}::ng-deep .ProseMirror-icon svg{fill:currentColor;height:1em}::ng-deep .ProseMirror-icon span{vertical-align:text-top}::ng-deep .ProseMirror-gapcursor{display:none;pointer-events:none;position:absolute}::ng-deep .ProseMirror-gapcursor:after{content:\"\";display:block;position:absolute;top:-2px;width:20px;border-top:1px solid black;animation:ProseMirror-cursor-blink 1.1s steps(2,start) infinite}@keyframes ProseMirror-cursor-blink{to{visibility:hidden}}::ng-deep .ProseMirror-focused .ProseMirror-gapcursor{display:block}::ng-deep .ProseMirror ul,::ng-deep .ProseMirror ol{padding-left:30px;list-style-position:initial}::ng-deep .ProseMirror blockquote{padding-left:1em;border-left:3px solid var(--color-grey-100);margin-left:0;margin-right:0}::ng-deep .ProseMirror-prompt{background:white;padding:5px 10px 5px 15px;border:1px solid silver;position:fixed;border-radius:3px;z-index:11;box-shadow:-.5px 2px 5px #0003}::ng-deep .ProseMirror-prompt h5{margin:0;font-weight:400;font-size:100%;color:var(--color-grey-500)}::ng-deep .ProseMirror-prompt input[type=text],::ng-deep .ProseMirror-prompt textarea{background:var(--color-component-bg-100);border:none;outline:none}::ng-deep .ProseMirror-prompt input[type=text]{padding:0 4px}::ng-deep .ProseMirror-prompt-close{position:absolute;left:2px;top:1px;color:var(--color-grey-400);border:none;background:transparent;padding:0}::ng-deep .ProseMirror-prompt-close:after{content:\"\\e2\\153\\2022\";font-size:12px}::ng-deep .ProseMirror-invalid{background:var(--color-warning-200);border:1px solid var(--color-warning-300);border-radius:4px;padding:5px 10px;position:absolute;min-width:10em}::ng-deep .ProseMirror-prompt-buttons{margin-top:5px;display:none}::ng-deep #editor,::ng-deep .editor{background:var(--color-form-input-bg);color:#000;background-clip:padding-box;border-radius:4px;border:2px solid rgba(0,0,0,.2);padding:5px 0;margin-bottom:23px}::ng-deep .ProseMirror p:first-child,::ng-deep .ProseMirror h1:first-child,::ng-deep .ProseMirror h2:first-child,::ng-deep .ProseMirror h3:first-child,::ng-deep .ProseMirror h4:first-child,::ng-deep .ProseMirror h5:first-child,::ng-deep .ProseMirror h6:first-child{margin-top:10px}::ng-deep .ProseMirror{padding:4px 8px 4px 14px;line-height:1.2;outline:none}::ng-deep .ProseMirror p{margin-bottom:.5rem;color:var(--color-grey-800)!important}:host{display:block;max-width:710px;margin-bottom:.5rem}:host.readonly ::ng-deep .ProseMirror-menubar{display:none}::ng-deep .ProseMirror-menubar{position:sticky;top:24px;margin-top:6px;border:1px solid var(--color-component-border-200);border-bottom:none;background-color:var(--color-component-bg-200);color:var(--color-icon-button);border-radius:var(--border-radius-input) var(--border-radius-input) 0 0;padding:6px 12px;display:flex;flex-wrap:wrap}::ng-deep .vdr-prosemirror{background:var(--color-form-input-bg);min-height:128px;min-width:200px;border:1px solid var(--color-component-border-200);border-radius:0 0 var(--border-radius-input) var(--border-radius-input);transition:border-color .2s;overflow:auto;text-align:initial}::ng-deep .vdr-prosemirror:focus{border-color:var(--color-primary-500)!important;box-shadow:0 0 1px 1px var(--color-primary-100)}::ng-deep .vdr-prosemirror hr{padding:2px 10px;border:none;margin:1em 0}::ng-deep .vdr-prosemirror hr:after{content:\"\";display:block;height:1px;background-color:silver;line-height:2px}::ng-deep .vdr-prosemirror img{cursor:default;max-width:100%}\n"], directives: [{ type: i1$3.ClrLabel, selector: "label", inputs: ["for"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13348
13927
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: RichTextEditorComponent, decorators: [{
13349
13928
  type: Component,
13350
13929
  args: [{ selector: 'vdr-rich-text-editor', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
@@ -13354,7 +13933,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImpor
13354
13933
  multi: true,
13355
13934
  },
13356
13935
  ProsemirrorService,
13357
- ], template: "<label class=\"clr-control-label\">{{ label }}</label>\r\n<div #editor></div>\r\n", styles: ["@charset \"UTF-8\";::ng-deep .ProseMirror{position:relative}::ng-deep .ProseMirror{word-wrap:break-word;white-space:pre-wrap;-webkit-font-variant-ligatures:none;font-feature-settings:none;font-variant-ligatures:none}::ng-deep .ProseMirror pre{white-space:pre-wrap}::ng-deep .ProseMirror li{position:relative}::ng-deep .ProseMirror-hideselection *::selection{background:transparent}::ng-deep .ProseMirror-hideselection *::-moz-selection{background:transparent}::ng-deep .ProseMirror-hideselection{caret-color:transparent}::ng-deep .ProseMirror-selectednode{outline:2px solid var(--color-primary-500)}::ng-deep li.ProseMirror-selectednode{outline:none}::ng-deep li.ProseMirror-selectednode:after{content:\"\";position:absolute;left:-32px;right:-2px;top:-2px;bottom:-2px;border:2px solid var(--color-primary-500);pointer-events:none}::ng-deep .ProseMirror-textblock-dropdown{min-width:3em}::ng-deep .ProseMirror-menu{margin:0 -4px;line-height:1}::ng-deep .ProseMirror-tooltip .ProseMirror-menu{width:-moz-fit-content;width:fit-content;white-space:pre}::ng-deep .ProseMirror-menuitem{margin-right:3px;display:inline-block}::ng-deep .ProseMirror-menuseparator{border-right:1px solid var(--color-component-border-200);margin-right:3px}::ng-deep .ProseMirror-menu-dropdown,::ng-deep .ProseMirror-menu-dropdown-menu{font-size:90%;white-space:nowrap}::ng-deep .ProseMirror-menu-dropdown{vertical-align:1px;cursor:pointer;position:relative;padding-right:15px}::ng-deep .ProseMirror-menu-dropdown-wrap{padding:1px 0 1px 4px;display:inline-block;position:relative}::ng-deep .ProseMirror-menu-dropdown:after{content:\"\";border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid currentColor;opacity:.6;position:absolute;right:4px;top:calc(50% - 2px)}::ng-deep .ProseMirror-menu-dropdown-menu,::ng-deep .ProseMirror-menu-submenu{position:absolute;background:white;color:var(--color-grey-600);border:1px solid var(--color-component-border-200);padding:2px}::ng-deep .ProseMirror-menu-dropdown-menu{z-index:15;min-width:6em}::ng-deep .ProseMirror-menu-dropdown-item{cursor:pointer;padding:2px 8px 2px 4px}::ng-deep .ProseMirror-menu-dropdown-item:hover{background:var(--color-component-bg-100)}::ng-deep .ProseMirror-menu-submenu-wrap{position:relative;margin-right:-4px}::ng-deep .ProseMirror-menu-submenu-label:after{content:\"\";border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid currentColor;opacity:.6;position:absolute;right:4px;top:calc(50% - 4px)}::ng-deep .ProseMirror-menu-submenu{display:none;min-width:4em;left:100%;top:-3px}::ng-deep .ProseMirror-menu-active{background:var(--color-component-bg-100);border-radius:4px}::ng-deep .ProseMirror-menu-disabled{opacity:.3}::ng-deep .ProseMirror-menu-submenu-wrap:hover .ProseMirror-menu-submenu,::ng-deep .ProseMirror-menu-submenu-wrap-active .ProseMirror-menu-submenu{display:block}::ng-deep .ProseMirror-menubar{border-top-left-radius:inherit;border-top-right-radius:inherit;position:relative;min-height:1em;color:var(--color-grey-600);padding:1px 6px;top:0;left:0;right:0;background:var(--color-component-bg-100);z-index:10;box-sizing:border-box;overflow:visible}::ng-deep .ProseMirror-icon{display:inline-block;line-height:.8;vertical-align:-2px;padding:2px 8px;cursor:pointer}::ng-deep .ProseMirror-menu-disabled.ProseMirror-icon{cursor:default}::ng-deep .ProseMirror-icon svg{fill:currentColor;height:1em}::ng-deep .ProseMirror-icon span{vertical-align:text-top}::ng-deep .ProseMirror-gapcursor{display:none;pointer-events:none;position:absolute}::ng-deep .ProseMirror-gapcursor:after{content:\"\";display:block;position:absolute;top:-2px;width:20px;border-top:1px solid black;animation:ProseMirror-cursor-blink 1.1s steps(2,start) infinite}@keyframes ProseMirror-cursor-blink{to{visibility:hidden}}::ng-deep .ProseMirror-focused .ProseMirror-gapcursor{display:block}::ng-deep .ProseMirror ul,::ng-deep .ProseMirror ol{padding-left:30px;list-style-position:initial}::ng-deep .ProseMirror blockquote{padding-left:1em;border-left:3px solid var(--color-grey-100);margin-left:0;margin-right:0}::ng-deep .ProseMirror-prompt{background:white;padding:5px 10px 5px 15px;border:1px solid silver;position:fixed;border-radius:3px;z-index:11;box-shadow:-.5px 2px 5px #0003}::ng-deep .ProseMirror-prompt h5{margin:0;font-weight:400;font-size:100%;color:var(--color-grey-500)}::ng-deep .ProseMirror-prompt input[type=text],::ng-deep .ProseMirror-prompt textarea{background:var(--color-component-bg-100);border:none;outline:none}::ng-deep .ProseMirror-prompt input[type=text]{padding:0 4px}::ng-deep .ProseMirror-prompt-close{position:absolute;left:2px;top:1px;color:var(--color-grey-400);border:none;background:transparent;padding:0}::ng-deep .ProseMirror-prompt-close:after{content:\"\\e2\\153\\2022\";font-size:12px}::ng-deep .ProseMirror-invalid{background:var(--color-warning-200);border:1px solid var(--color-warning-300);border-radius:4px;padding:5px 10px;position:absolute;min-width:10em}::ng-deep .ProseMirror-prompt-buttons{margin-top:5px;display:none}::ng-deep #editor,::ng-deep .editor{background:var(--color-form-input-bg);color:#000;background-clip:padding-box;border-radius:4px;border:2px solid rgba(0,0,0,.2);padding:5px 0;margin-bottom:23px}::ng-deep .ProseMirror p:first-child,::ng-deep .ProseMirror h1:first-child,::ng-deep .ProseMirror h2:first-child,::ng-deep .ProseMirror h3:first-child,::ng-deep .ProseMirror h4:first-child,::ng-deep .ProseMirror h5:first-child,::ng-deep .ProseMirror h6:first-child{margin-top:10px}::ng-deep .ProseMirror{padding:4px 8px 4px 14px;line-height:1.2;outline:none}::ng-deep .ProseMirror p{margin-bottom:.5rem;color:var(--color-grey-800)!important}:host{display:block;max-width:710px;margin-bottom:.5rem}:host.readonly ::ng-deep .ProseMirror-menubar{display:none}::ng-deep .ProseMirror-menubar{position:sticky;top:24px;margin-top:6px;border:1px solid var(--color-component-border-200);border-bottom:none;background-color:var(--color-component-bg-200);color:var(--color-icon-button);padding:6px 12px;display:flex;flex-wrap:wrap}::ng-deep .vdr-prosemirror{background:var(--color-form-input-bg);min-height:128px;min-width:200px;border:1px solid var(--color-component-border-200);border-radius:0 0 3px 3px;transition:border-color .2s;overflow:auto;text-align:initial}::ng-deep .vdr-prosemirror:focus{border-color:var(--color-primary-500)!important;box-shadow:0 0 1px 1px var(--color-primary-100)}::ng-deep .vdr-prosemirror hr{padding:2px 10px;border:none;margin:1em 0}::ng-deep .vdr-prosemirror hr:after{content:\"\";display:block;height:1px;background-color:silver;line-height:2px}::ng-deep .vdr-prosemirror img{cursor:default;max-width:100%}\n"] }]
13936
+ ], template: "<label class=\"clr-control-label\">{{ label }}</label>\r\n<div #editor></div>\r\n", styles: ["@charset \"UTF-8\";::ng-deep .ProseMirror{position:relative}::ng-deep .ProseMirror{word-wrap:break-word;white-space:pre-wrap;-webkit-font-variant-ligatures:none;font-feature-settings:none;font-variant-ligatures:none}::ng-deep .ProseMirror pre{white-space:pre-wrap}::ng-deep .ProseMirror li{position:relative}::ng-deep .ProseMirror-hideselection *::selection{background:transparent}::ng-deep .ProseMirror-hideselection *::-moz-selection{background:transparent}::ng-deep .ProseMirror-hideselection{caret-color:transparent}::ng-deep .ProseMirror-selectednode{outline:2px solid var(--color-primary-500)}::ng-deep li.ProseMirror-selectednode{outline:none}::ng-deep li.ProseMirror-selectednode:after{content:\"\";position:absolute;left:-32px;right:-2px;top:-2px;bottom:-2px;border:2px solid var(--color-primary-500);pointer-events:none}::ng-deep .ProseMirror-textblock-dropdown{min-width:3em}::ng-deep .ProseMirror-menu{margin:0 -4px;line-height:1}::ng-deep .ProseMirror-tooltip .ProseMirror-menu{width:-moz-fit-content;width:fit-content;white-space:pre}::ng-deep .ProseMirror-menuitem{margin-right:3px;display:inline-block}::ng-deep .ProseMirror-menuseparator{border-right:1px solid var(--color-component-border-200);margin-right:3px}::ng-deep .ProseMirror-menu-dropdown,::ng-deep .ProseMirror-menu-dropdown-menu{font-size:90%;white-space:nowrap}::ng-deep .ProseMirror-menu-dropdown{vertical-align:1px;cursor:pointer;position:relative;padding-right:15px}::ng-deep .ProseMirror-menu-dropdown-wrap{padding:1px 0 1px 4px;display:inline-block;position:relative}::ng-deep .ProseMirror-menu-dropdown:after{content:\"\";border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid currentColor;opacity:.6;position:absolute;right:4px;top:calc(50% - 2px)}::ng-deep .ProseMirror-menu-dropdown-menu,::ng-deep .ProseMirror-menu-submenu{position:absolute;background:white;color:var(--color-grey-600);border:1px solid var(--color-component-border-200);padding:2px}::ng-deep .ProseMirror-menu-dropdown-menu{z-index:15;min-width:6em}::ng-deep .ProseMirror-menu-dropdown-item{cursor:pointer;padding:2px 8px 2px 4px}::ng-deep .ProseMirror-menu-dropdown-item:hover{background:var(--color-component-bg-100)}::ng-deep .ProseMirror-menu-submenu-wrap{position:relative;margin-right:-4px}::ng-deep .ProseMirror-menu-submenu-label:after{content:\"\";border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:4px solid currentColor;opacity:.6;position:absolute;right:4px;top:calc(50% - 4px)}::ng-deep .ProseMirror-menu-submenu{display:none;min-width:4em;left:100%;top:-3px}::ng-deep .ProseMirror-menu-active{background:var(--color-component-bg-100);border-radius:4px}::ng-deep .ProseMirror-menu-disabled{opacity:.3}::ng-deep .ProseMirror-menu-submenu-wrap:hover .ProseMirror-menu-submenu,::ng-deep .ProseMirror-menu-submenu-wrap-active .ProseMirror-menu-submenu{display:block}::ng-deep .ProseMirror-menubar{border-top-left-radius:inherit;border-top-right-radius:inherit;position:relative;min-height:1em;color:var(--color-grey-600);padding:1px 6px;top:0;left:0;right:0;background:var(--color-component-bg-100);z-index:10;box-sizing:border-box;overflow:visible}::ng-deep .ProseMirror-icon{display:inline-block;line-height:.8;vertical-align:-2px;padding:2px 8px;cursor:pointer}::ng-deep .ProseMirror-menu-disabled.ProseMirror-icon{cursor:default}::ng-deep .ProseMirror-icon svg{fill:currentColor;height:1em}::ng-deep .ProseMirror-icon span{vertical-align:text-top}::ng-deep .ProseMirror-gapcursor{display:none;pointer-events:none;position:absolute}::ng-deep .ProseMirror-gapcursor:after{content:\"\";display:block;position:absolute;top:-2px;width:20px;border-top:1px solid black;animation:ProseMirror-cursor-blink 1.1s steps(2,start) infinite}@keyframes ProseMirror-cursor-blink{to{visibility:hidden}}::ng-deep .ProseMirror-focused .ProseMirror-gapcursor{display:block}::ng-deep .ProseMirror ul,::ng-deep .ProseMirror ol{padding-left:30px;list-style-position:initial}::ng-deep .ProseMirror blockquote{padding-left:1em;border-left:3px solid var(--color-grey-100);margin-left:0;margin-right:0}::ng-deep .ProseMirror-prompt{background:white;padding:5px 10px 5px 15px;border:1px solid silver;position:fixed;border-radius:3px;z-index:11;box-shadow:-.5px 2px 5px #0003}::ng-deep .ProseMirror-prompt h5{margin:0;font-weight:400;font-size:100%;color:var(--color-grey-500)}::ng-deep .ProseMirror-prompt input[type=text],::ng-deep .ProseMirror-prompt textarea{background:var(--color-component-bg-100);border:none;outline:none}::ng-deep .ProseMirror-prompt input[type=text]{padding:0 4px}::ng-deep .ProseMirror-prompt-close{position:absolute;left:2px;top:1px;color:var(--color-grey-400);border:none;background:transparent;padding:0}::ng-deep .ProseMirror-prompt-close:after{content:\"\\e2\\153\\2022\";font-size:12px}::ng-deep .ProseMirror-invalid{background:var(--color-warning-200);border:1px solid var(--color-warning-300);border-radius:4px;padding:5px 10px;position:absolute;min-width:10em}::ng-deep .ProseMirror-prompt-buttons{margin-top:5px;display:none}::ng-deep #editor,::ng-deep .editor{background:var(--color-form-input-bg);color:#000;background-clip:padding-box;border-radius:4px;border:2px solid rgba(0,0,0,.2);padding:5px 0;margin-bottom:23px}::ng-deep .ProseMirror p:first-child,::ng-deep .ProseMirror h1:first-child,::ng-deep .ProseMirror h2:first-child,::ng-deep .ProseMirror h3:first-child,::ng-deep .ProseMirror h4:first-child,::ng-deep .ProseMirror h5:first-child,::ng-deep .ProseMirror h6:first-child{margin-top:10px}::ng-deep .ProseMirror{padding:4px 8px 4px 14px;line-height:1.2;outline:none}::ng-deep .ProseMirror p{margin-bottom:.5rem;color:var(--color-grey-800)!important}:host{display:block;max-width:710px;margin-bottom:.5rem}:host.readonly ::ng-deep .ProseMirror-menubar{display:none}::ng-deep .ProseMirror-menubar{position:sticky;top:24px;margin-top:6px;border:1px solid var(--color-component-border-200);border-bottom:none;background-color:var(--color-component-bg-200);color:var(--color-icon-button);border-radius:var(--border-radius-input) var(--border-radius-input) 0 0;padding:6px 12px;display:flex;flex-wrap:wrap}::ng-deep .vdr-prosemirror{background:var(--color-form-input-bg);min-height:128px;min-width:200px;border:1px solid var(--color-component-border-200);border-radius:0 0 var(--border-radius-input) var(--border-radius-input);transition:border-color .2s;overflow:auto;text-align:initial}::ng-deep .vdr-prosemirror:focus{border-color:var(--color-primary-500)!important;box-shadow:0 0 1px 1px var(--color-primary-100)}::ng-deep .vdr-prosemirror hr{padding:2px 10px;border:none;margin:1em 0}::ng-deep .vdr-prosemirror hr:after{content:\"\";display:block;height:1px;background-color:silver;line-height:2px}::ng-deep .vdr-prosemirror img{cursor:default;max-width:100%}\n"] }]
13358
13937
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: ProsemirrorService }]; }, propDecorators: { label: [{
13359
13938
  type: Input
13360
13939
  }], readonly: [{
@@ -13468,6 +14047,8 @@ const defaultFormInputs = [
13468
14047
  TextareaFormInputComponent,
13469
14048
  RichTextFormInputComponent,
13470
14049
  JsonEditorFormInputComponent,
14050
+ ProductMultiSelectorFormInputComponent,
14051
+ CombinationModeFormInputComponent,
13471
14052
  ];
13472
14053
  /**
13473
14054
  * @description
@@ -13966,196 +14547,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImpor
13966
14547
  type: Input
13967
14548
  }] } });
13968
14549
 
13969
- /**
13970
- * Interpolates the description of an ConfigurableOperation with the given values.
13971
- */
13972
- function interpolateDescription(operation, values) {
13973
- if (!operation) {
13974
- return '';
13975
- }
13976
- const templateString = operation.description;
13977
- const interpolated = templateString.replace(/{\s*([a-zA-Z0-9]+)\s*}/gi, (substring, argName) => {
13978
- const normalizedArgName = argName.toLowerCase();
13979
- const value = values[normalizedArgName];
13980
- if (value == null) {
13981
- return '_';
13982
- }
13983
- let formatted = value;
13984
- const argDef = operation.args.find(arg => arg.name === normalizedArgName);
13985
- if (argDef && argDef.type === 'int' && argDef.ui && argDef.ui.component === 'currency-form-input') {
13986
- formatted = value / 100;
13987
- }
13988
- if (argDef && argDef.type === 'datetime' && value instanceof Date) {
13989
- formatted = value.toLocaleDateString();
13990
- }
13991
- return formatted;
13992
- });
13993
- return interpolated;
13994
- }
13995
-
13996
- /**
13997
- * Formats a string into sentence case (first letter of first word uppercase).
13998
- */
13999
- class SentenceCasePipe {
14000
- transform(value) {
14001
- if (typeof value === 'string') {
14002
- let lower;
14003
- if (isCamelCase(value)) {
14004
- lower = value.replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase();
14005
- }
14006
- else {
14007
- lower = value.toLowerCase();
14008
- }
14009
- return lower.charAt(0).toUpperCase() + lower.slice(1);
14010
- }
14011
- return value;
14012
- }
14013
- }
14014
- SentenceCasePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SentenceCasePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
14015
- SentenceCasePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SentenceCasePipe, name: "sentenceCase" });
14016
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SentenceCasePipe, decorators: [{
14017
- type: Pipe,
14018
- args: [{ name: 'sentenceCase' }]
14019
- }] });
14020
- function isCamelCase(value) {
14021
- return /^[a-zA-Z]+[A-Z][a-zA-Z]+$/.test(value);
14022
- }
14023
-
14024
- /**
14025
- * A form input which renders a card with the internal form fields of the given ConfigurableOperation.
14026
- */
14027
- class ConfigurableInputComponent {
14028
- constructor() {
14029
- this.readonly = false;
14030
- this.removable = true;
14031
- this.remove = new EventEmitter();
14032
- this.argValues = {};
14033
- this.form = new FormGroup({});
14034
- }
14035
- interpolateDescription() {
14036
- if (this.operationDefinition) {
14037
- return interpolateDescription(this.operationDefinition, this.form.value);
14038
- }
14039
- else {
14040
- return '';
14041
- }
14042
- }
14043
- ngOnChanges(changes) {
14044
- if ('operation' in changes || 'operationDefinition' in changes) {
14045
- this.createForm();
14046
- }
14047
- }
14048
- ngOnDestroy() {
14049
- if (this.subscription) {
14050
- this.subscription.unsubscribe();
14051
- }
14052
- }
14053
- registerOnChange(fn) {
14054
- this.onChange = fn;
14055
- }
14056
- registerOnTouched(fn) {
14057
- this.onTouch = fn;
14058
- }
14059
- setDisabledState(isDisabled) {
14060
- if (isDisabled) {
14061
- this.form.disable();
14062
- }
14063
- else {
14064
- this.form.enable();
14065
- }
14066
- }
14067
- writeValue(value) {
14068
- if (value) {
14069
- this.form.patchValue(value);
14070
- }
14071
- }
14072
- trackByName(index, arg) {
14073
- return arg.name;
14074
- }
14075
- getArgDef(arg) {
14076
- var _a;
14077
- return (_a = this.operationDefinition) === null || _a === void 0 ? void 0 : _a.args.find(a => a.name === arg.name);
14078
- }
14079
- createForm() {
14080
- var _a, _b;
14081
- if (!this.operation) {
14082
- return;
14083
- }
14084
- if (this.subscription) {
14085
- this.subscription.unsubscribe();
14086
- }
14087
- this.form = new FormGroup({});
14088
- this.form.__id = Math.random().toString(36).substr(10);
14089
- if (this.operation.args) {
14090
- for (const arg of ((_a = this.operationDefinition) === null || _a === void 0 ? void 0 : _a.args) || []) {
14091
- let value = (_b = this.operation.args.find(a => a.name === arg.name)) === null || _b === void 0 ? void 0 : _b.value;
14092
- if (value === undefined) {
14093
- value = getDefaultConfigArgValue(arg);
14094
- }
14095
- const validators = arg.list ? undefined : arg.required ? Validators.required : undefined;
14096
- this.form.addControl(arg.name, new FormControl(value, validators));
14097
- }
14098
- }
14099
- this.subscription = this.form.valueChanges.subscribe(value => {
14100
- if (this.onChange) {
14101
- this.onChange({
14102
- code: this.operation && this.operation.code,
14103
- args: value,
14104
- });
14105
- }
14106
- if (this.onTouch) {
14107
- this.onTouch();
14108
- }
14109
- });
14110
- }
14111
- validate(c) {
14112
- if (this.form.invalid) {
14113
- return {
14114
- required: true,
14115
- };
14116
- }
14117
- return null;
14118
- }
14119
- }
14120
- ConfigurableInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ConfigurableInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14121
- ConfigurableInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: ConfigurableInputComponent, selector: "vdr-configurable-input", inputs: { operation: "operation", operationDefinition: "operationDefinition", readonly: "readonly", removable: "removable" }, outputs: { remove: "remove" }, providers: [
14122
- {
14123
- provide: NG_VALUE_ACCESSOR,
14124
- useExisting: ConfigurableInputComponent,
14125
- multi: true,
14126
- },
14127
- {
14128
- provide: NG_VALIDATORS,
14129
- useExisting: forwardRef(() => ConfigurableInputComponent),
14130
- multi: true,
14131
- },
14132
- ], usesOnChanges: true, ngImport: i0, template: "<div class=\"card\" *ngIf=\"operation\">\r\n <div class=\"card-block\">{{ interpolateDescription() }}</div>\r\n <div class=\"card-block\" *ngIf=\"operation.args?.length\">\r\n <form [formGroup]=\"form\" *ngIf=\"operation\" class=\"operation-inputs\">\r\n <div *ngFor=\"let arg of operation.args; trackBy: trackByName\" class=\"arg-row\">\r\n <ng-container *ngIf=\"form.get(arg.name) && getArgDef(arg) as argDef\">\r\n <label class=\"clr-control-label\">{{ argDef.label || (arg.name | sentenceCase) }}</label>\r\n <vdr-help-tooltip\r\n class=\"mr3\"\r\n *ngIf=\"argDef.description\"\r\n [content]=\"argDef.description\"\r\n ></vdr-help-tooltip>\r\n <vdr-dynamic-form-input\r\n [def]=\"getArgDef(arg)\"\r\n [readonly]=\"readonly\"\r\n [control]=\"form.get(arg.name)\"\r\n [formControlName]=\"arg.name\"\r\n ></vdr-dynamic-form-input>\r\n </ng-container>\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"card-footer\" *ngIf=\"!readonly && removable\">\r\n <button class=\"btn btn-sm btn-link btn-warning\" (click)=\"remove.emit(operation)\">\r\n <clr-icon shape=\"times\"></clr-icon>\r\n {{ 'common.remove' | translate }}\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;margin-bottom:12px}:host>.card{margin-top:6px}.operation-inputs{padding-top:0}.operation-inputs .arg-row:not(:last-child){margin-bottom:12px}.operation-inputs .arg-row{display:flex;flex-wrap:wrap;align-items:center}.operation-inputs .arg-row label{margin-right:6px}.operation-inputs .hidden{display:none}\n"], components: [{ type: HelpTooltipComponent, selector: "vdr-help-tooltip", inputs: ["content", "position"] }, { type: DynamicFormInputComponent, selector: "vdr-dynamic-form-input", inputs: ["def", "readonly", "control"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1$3.ClrDatagridItemsTrackBy, selector: "[ngForTrackBy]", inputs: ["ngForTrackBy"] }, { type: i1$3.ClrLabel, selector: "label", inputs: ["for"] }, { type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i1$3.ClrIconCustomTag, selector: "clr-icon" }], pipes: { "sentenceCase": SentenceCasePipe, "translate": i7.TranslatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
14133
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: ConfigurableInputComponent, decorators: [{
14134
- type: Component,
14135
- args: [{ selector: 'vdr-configurable-input', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
14136
- {
14137
- provide: NG_VALUE_ACCESSOR,
14138
- useExisting: ConfigurableInputComponent,
14139
- multi: true,
14140
- },
14141
- {
14142
- provide: NG_VALIDATORS,
14143
- useExisting: forwardRef(() => ConfigurableInputComponent),
14144
- multi: true,
14145
- },
14146
- ], template: "<div class=\"card\" *ngIf=\"operation\">\r\n <div class=\"card-block\">{{ interpolateDescription() }}</div>\r\n <div class=\"card-block\" *ngIf=\"operation.args?.length\">\r\n <form [formGroup]=\"form\" *ngIf=\"operation\" class=\"operation-inputs\">\r\n <div *ngFor=\"let arg of operation.args; trackBy: trackByName\" class=\"arg-row\">\r\n <ng-container *ngIf=\"form.get(arg.name) && getArgDef(arg) as argDef\">\r\n <label class=\"clr-control-label\">{{ argDef.label || (arg.name | sentenceCase) }}</label>\r\n <vdr-help-tooltip\r\n class=\"mr3\"\r\n *ngIf=\"argDef.description\"\r\n [content]=\"argDef.description\"\r\n ></vdr-help-tooltip>\r\n <vdr-dynamic-form-input\r\n [def]=\"getArgDef(arg)\"\r\n [readonly]=\"readonly\"\r\n [control]=\"form.get(arg.name)\"\r\n [formControlName]=\"arg.name\"\r\n ></vdr-dynamic-form-input>\r\n </ng-container>\r\n </div>\r\n </form>\r\n </div>\r\n <div class=\"card-footer\" *ngIf=\"!readonly && removable\">\r\n <button class=\"btn btn-sm btn-link btn-warning\" (click)=\"remove.emit(operation)\">\r\n <clr-icon shape=\"times\"></clr-icon>\r\n {{ 'common.remove' | translate }}\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;margin-bottom:12px}:host>.card{margin-top:6px}.operation-inputs{padding-top:0}.operation-inputs .arg-row:not(:last-child){margin-bottom:12px}.operation-inputs .arg-row{display:flex;flex-wrap:wrap;align-items:center}.operation-inputs .arg-row label{margin-right:6px}.operation-inputs .hidden{display:none}\n"] }]
14147
- }], propDecorators: { operation: [{
14148
- type: Input
14149
- }], operationDefinition: [{
14150
- type: Input
14151
- }], readonly: [{
14152
- type: Input
14153
- }], removable: [{
14154
- type: Input
14155
- }], remove: [{
14156
- type: Output
14157
- }] } });
14158
-
14159
14550
  /**
14160
14551
  * @description
14161
14552
  * Registers a {@link CustomDetailComponent} to be placed in a given location. This allows you
@@ -14747,34 +15138,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImpor
14747
15138
  type: Input
14748
15139
  }] } });
14749
15140
 
14750
- /**
14751
- * A simple, stateless toggle button for indicating selection.
14752
- */
14753
- class SelectToggleComponent {
14754
- constructor() {
14755
- this.size = 'large';
14756
- this.selected = false;
14757
- this.disabled = false;
14758
- this.selectedChange = new EventEmitter();
14759
- }
14760
- }
14761
- SelectToggleComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SelectToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14762
- SelectToggleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.3", type: SelectToggleComponent, selector: "vdr-select-toggle", inputs: { size: "size", selected: "selected", disabled: "disabled", label: "label" }, outputs: { selectedChange: "selectedChange" }, ngImport: i0, template: "<div\r\n class=\"toggle\"\r\n [class.disabled]=\"disabled\"\r\n [class.small]=\"size === 'small'\"\r\n [attr.tabindex]=\"disabled ? null : 0\"\r\n [class.selected]=\"selected\"\r\n (keydown.enter)=\"selectedChange.emit(!selected)\"\r\n (keydown.space)=\"$event.preventDefault(); selectedChange.emit(!selected)\"\r\n (click)=\"selectedChange.emit(!selected)\"\r\n>\r\n <clr-icon shape=\"check\" [attr.size]=\"size === 'small' ? 16 : 32\"></clr-icon>\r\n</div>\r\n<div class=\"toggle-label\" [class.disabled]=\"disabled\" *ngIf=\"label\" (click)=\"selectedChange.emit(!selected)\">\r\n {{ label }}\r\n</div>\r\n", styles: [":host{display:flex;align-items:center;justify-content:center}.toggle{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;cursor:pointer;background-color:var(--color-component-bg-100);border:2px solid var(--color-component-border-300);padding:0 6px;border-radius:50%;width:32px;height:32px;display:flex;align-items:center;justify-content:center;color:var(--color-grey-300);transition:background-color .2s,border .2s}.toggle.small{width:24px;height:24px}.toggle:not(.disabled):hover{border-color:var(--color-success-500);background-color:var(--color-success-400);opacity:.9}.toggle.selected{background-color:var(--color-success-500);border-color:var(--color-success-600);color:#fff}.toggle.selected:not(.disabled):hover{background-color:var(--color-success-500);border-color:var(--color-success-400);opacity:.9}.toggle:focus{outline:none;box-shadow:0 0 2px 2px var(--color-primary-500)}.toggle.disabled{cursor:default}.toggle-label{flex:1;margin-left:6px;text-align:left;font-size:12px}.toggle-label:not(.disabled){cursor:pointer}\n"], directives: [{ type: i1$3.ClrIconCustomTag, selector: "clr-icon" }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
14763
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SelectToggleComponent, decorators: [{
14764
- type: Component,
14765
- args: [{ selector: 'vdr-select-toggle', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\r\n class=\"toggle\"\r\n [class.disabled]=\"disabled\"\r\n [class.small]=\"size === 'small'\"\r\n [attr.tabindex]=\"disabled ? null : 0\"\r\n [class.selected]=\"selected\"\r\n (keydown.enter)=\"selectedChange.emit(!selected)\"\r\n (keydown.space)=\"$event.preventDefault(); selectedChange.emit(!selected)\"\r\n (click)=\"selectedChange.emit(!selected)\"\r\n>\r\n <clr-icon shape=\"check\" [attr.size]=\"size === 'small' ? 16 : 32\"></clr-icon>\r\n</div>\r\n<div class=\"toggle-label\" [class.disabled]=\"disabled\" *ngIf=\"label\" (click)=\"selectedChange.emit(!selected)\">\r\n {{ label }}\r\n</div>\r\n", styles: [":host{display:flex;align-items:center;justify-content:center}.toggle{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;cursor:pointer;background-color:var(--color-component-bg-100);border:2px solid var(--color-component-border-300);padding:0 6px;border-radius:50%;width:32px;height:32px;display:flex;align-items:center;justify-content:center;color:var(--color-grey-300);transition:background-color .2s,border .2s}.toggle.small{width:24px;height:24px}.toggle:not(.disabled):hover{border-color:var(--color-success-500);background-color:var(--color-success-400);opacity:.9}.toggle.selected{background-color:var(--color-success-500);border-color:var(--color-success-600);color:#fff}.toggle.selected:not(.disabled):hover{background-color:var(--color-success-500);border-color:var(--color-success-400);opacity:.9}.toggle:focus{outline:none;box-shadow:0 0 2px 2px var(--color-primary-500)}.toggle.disabled{cursor:default}.toggle-label{flex:1;margin-left:6px;text-align:left;font-size:12px}.toggle-label:not(.disabled){cursor:pointer}\n"] }]
14766
- }], propDecorators: { size: [{
14767
- type: Input
14768
- }], selected: [{
14769
- type: Input
14770
- }], disabled: [{
14771
- type: Input
14772
- }], label: [{
14773
- type: Input
14774
- }], selectedChange: [{
14775
- type: Output
14776
- }] } });
14777
-
14778
15141
  /**
14779
15142
  * A button link to be used as actions in rows of a table.
14780
15143
  */
@@ -15117,6 +15480,8 @@ const DECLARATIONS = [
15117
15480
  UiExtensionPointComponent,
15118
15481
  CustomDetailComponentHostComponent,
15119
15482
  AssetPreviewLinksComponent,
15483
+ ProductMultiSelectorDialogComponent,
15484
+ ProductSearchInputComponent,
15120
15485
  ];
15121
15486
  const DYNAMIC_FORM_INPUTS = [
15122
15487
  TextFormInputComponent,
@@ -15140,6 +15505,8 @@ const DYNAMIC_FORM_INPUTS = [
15140
15505
  TextareaFormInputComponent,
15141
15506
  RichTextFormInputComponent,
15142
15507
  JsonEditorFormInputComponent,
15508
+ ProductMultiSelectorFormInputComponent,
15509
+ CombinationModeFormInputComponent,
15143
15510
  ];
15144
15511
  class SharedModule {
15145
15512
  }
@@ -15233,7 +15600,9 @@ SharedModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "
15233
15600
  TabbedCustomFieldsComponent,
15234
15601
  UiExtensionPointComponent,
15235
15602
  CustomDetailComponentHostComponent,
15236
- AssetPreviewLinksComponent, TextFormInputComponent,
15603
+ AssetPreviewLinksComponent,
15604
+ ProductMultiSelectorDialogComponent,
15605
+ ProductSearchInputComponent, TextFormInputComponent,
15237
15606
  PasswordFormInputComponent,
15238
15607
  NumberFormInputComponent,
15239
15608
  DateFormInputComponent,
@@ -15253,7 +15622,9 @@ SharedModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "
15253
15622
  RelationGenericInputComponent,
15254
15623
  TextareaFormInputComponent,
15255
15624
  RichTextFormInputComponent,
15256
- JsonEditorFormInputComponent], imports: [ClarityModule,
15625
+ JsonEditorFormInputComponent,
15626
+ ProductMultiSelectorFormInputComponent,
15627
+ CombinationModeFormInputComponent], imports: [ClarityModule,
15257
15628
  CommonModule,
15258
15629
  FormsModule,
15259
15630
  ReactiveFormsModule,
@@ -15360,7 +15731,9 @@ SharedModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "
15360
15731
  TabbedCustomFieldsComponent,
15361
15732
  UiExtensionPointComponent,
15362
15733
  CustomDetailComponentHostComponent,
15363
- AssetPreviewLinksComponent, TextFormInputComponent,
15734
+ AssetPreviewLinksComponent,
15735
+ ProductMultiSelectorDialogComponent,
15736
+ ProductSearchInputComponent, TextFormInputComponent,
15364
15737
  PasswordFormInputComponent,
15365
15738
  NumberFormInputComponent,
15366
15739
  DateFormInputComponent,
@@ -15380,7 +15753,9 @@ SharedModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "
15380
15753
  RelationGenericInputComponent,
15381
15754
  TextareaFormInputComponent,
15382
15755
  RichTextFormInputComponent,
15383
- JsonEditorFormInputComponent] });
15756
+ JsonEditorFormInputComponent,
15757
+ ProductMultiSelectorFormInputComponent,
15758
+ CombinationModeFormInputComponent] });
15384
15759
  SharedModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: SharedModule, providers: [
15385
15760
  // This needs to be shared, since lazy-loaded
15386
15761
  // modules have their own entryComponents which
@@ -15962,7 +16337,7 @@ function patchObject(obj, patch) {
15962
16337
  }
15963
16338
 
15964
16339
  // Auto-generated by the set-version.js script.
15965
- const ADMIN_UI_VERSION = '2.0.0-next.3';
16340
+ const ADMIN_UI_VERSION = '2.0.0-next.7';
15966
16341
 
15967
16342
  /**
15968
16343
  * Responsible for registering dashboard widget components and querying for layouts.
@@ -16182,5 +16557,5 @@ function unicodePatternValidator(patternRe) {
16182
16557
  * Generated bundle index. Do not edit.
16183
16558
  */
16184
16559
 
16185
- export { ADDRESS_FRAGMENT, ADD_CUSTOMERS_TO_GROUP, ADD_MANUAL_PAYMENT_TO_ORDER, ADD_MEMBERS_TO_ZONE, ADD_NOTE_TO_CUSTOMER, ADD_NOTE_TO_ORDER, ADD_OPTION_GROUP_TO_PRODUCT, ADD_OPTION_TO_GROUP, ADMINISTRATOR_FRAGMENT, ADMIN_UI_VERSION, ALL_CUSTOM_FIELDS_FRAGMENT, ASSET_FRAGMENT, ASSIGN_PRODUCTS_TO_CHANNEL, ASSIGN_ROLE_TO_ADMINISTRATOR, ASSIGN_VARIANTS_TO_CHANNEL, ATTEMPT_LOGIN, AUTH_REDIRECT_PARAM, ActionBarComponent, ActionBarItemsComponent, ActionBarLeftComponent, ActionBarRightComponent, AddressFormComponent, AdjustmentType, AdministratorDataService, AffixedInputComponent, AppComponent, AppComponentModule, AppShellComponent, AssetFileInputComponent, AssetGalleryComponent, AssetPickerDialogComponent, AssetPreviewComponent, AssetPreviewDialogComponent, AssetPreviewLinksComponent, AssetPreviewPipe, AssetSearchInputComponent, AssetType, AuthDataService, AuthGuard, AuthService, BOOLEAN_CUSTOM_FIELD_FRAGMENT, BaseDataService, BaseDetailComponent, BaseEntityResolver, BaseListComponent, BooleanFormInputComponent, BreadcrumbComponent, CANCEL_JOB, CANCEL_ORDER, CHANNEL_FRAGMENT, COLLECTION_FRAGMENT, CONFIGURABLE_OPERATION_DEF_FRAGMENT, CONFIGURABLE_OPERATION_FRAGMENT, COUNTRY_FRAGMENT, CREATE_ADMINISTRATOR, CREATE_ASSETS, CREATE_CHANNEL, CREATE_COLLECTION, CREATE_COUNTRY, CREATE_CUSTOMER, CREATE_CUSTOMER_ADDRESS, CREATE_CUSTOMER_GROUP, CREATE_FACET, CREATE_FACET_VALUES, CREATE_FULFILLMENT, CREATE_PAYMENT_METHOD, CREATE_PRODUCT, CREATE_PRODUCT_OPTION_GROUP, CREATE_PRODUCT_VARIANTS, CREATE_PROMOTION, CREATE_ROLE, CREATE_SHIPPING_METHOD, CREATE_TAG, CREATE_TAX_CATEGORY, CREATE_TAX_RATE, CREATE_ZONE, CURRENT_USER_FRAGMENT, CUSTOMER_FRAGMENT, CUSTOMER_GROUP_FRAGMENT, CUSTOM_FIELD_CONFIG_FRAGMENT, CanDeactivateDetailGuard, ChannelAssignmentControlComponent, ChannelBadgeComponent, ChannelLabelPipe, ChannelSwitcherComponent, CheckJobsLink, ChipComponent, ClientDataService, CollectionDataService, ComponentRegistryService, ConfigurableInputComponent, CoreModule, CurrencyCode, CurrencyFormInputComponent, CurrencyInputComponent, CustomDetailComponentHostComponent, CustomDetailComponentService, CustomFieldComponentService, CustomFieldControlComponent, CustomFieldLabelPipe, CustomHttpTranslationLoader, CustomerDataService, CustomerGroupFormInputComponent, CustomerLabelComponent, DATE_TIME_CUSTOM_FIELD_FRAGMENT, DELETE_ADMINISTRATOR, DELETE_ASSETS, DELETE_CHANNEL, DELETE_COLLECTION, DELETE_COUNTRY, DELETE_CUSTOMER, DELETE_CUSTOMER_ADDRESS, DELETE_CUSTOMER_GROUP, DELETE_CUSTOMER_NOTE, DELETE_FACET, DELETE_FACET_VALUES, DELETE_ORDER_NOTE, DELETE_PAYMENT_METHOD, DELETE_PRODUCT, DELETE_PRODUCT_VARIANT, DELETE_PROMOTION, DELETE_ROLE, DELETE_SHIPPING_METHOD, DELETE_TAG, DELETE_TAX_CATEGORY, DELETE_TAX_RATE, DELETE_ZONE, DISCOUNT_FRAGMENT, DashboardWidgetService, DataModule, DataService, DataTableColumnComponent, DataTableComponent, DateFormInputComponent, DatetimePickerComponent, DatetimePickerService, DefaultInterceptor, DeletionResult, DialogButtonsDirective, DialogComponentOutletComponent, DialogTitleDirective, DisabledDirective, DropdownComponent, DropdownItemDirective, DropdownMenuComponent, DropdownTriggerDirective, DurationPipe, DynamicFormInputComponent, ERROR_RESULT_FRAGMENT, EditNoteDialogComponent, EmptyPlaceholderComponent, EntityInfoComponent, ErrorCode, ExtensionHostComponent, ExtensionHostConfig, ExtensionHostService, ExternalImageDialogComponent, FACET_VALUE_FRAGMENT, FACET_WITH_VALUES_FRAGMENT, FLOAT_CUSTOM_FIELD_FRAGMENT, FULFILLMENT_FRAGMENT, FacetDataService, FacetValueChipComponent, FacetValueFormInputComponent, FacetValueSelectorComponent, FetchAdapter, FileSizePipe, FocalPointControlComponent, FormFieldComponent, FormFieldControlDirective, FormItemComponent, FormattedAddressComponent, GET_ACTIVE_ADMINISTRATOR, GET_ACTIVE_CHANNEL, GET_ADJUSTMENT_OPERATIONS, GET_ADMINISTRATOR, GET_ADMINISTRATORS, GET_ASSET, GET_ASSET_LIST, GET_AVAILABLE_COUNTRIES, GET_CHANNEL, GET_CHANNELS, GET_CLIENT_STATE, GET_COLLECTION, GET_COLLECTION_CONTENTS, GET_COLLECTION_FILTERS, GET_COLLECTION_LIST, GET_COUNTRY, GET_COUNTRY_LIST, GET_CURRENT_USER, GET_CUSTOMER, GET_CUSTOMER_GROUPS, GET_CUSTOMER_GROUP_WITH_CUSTOMERS, GET_CUSTOMER_HISTORY, GET_CUSTOMER_LIST, GET_FACET_LIST, GET_FACET_WITH_VALUES, GET_GLOBAL_SETTINGS, GET_JOBS_BY_ID, GET_JOBS_LIST, GET_JOB_INFO, GET_JOB_QUEUE_LIST, GET_NEWTORK_STATUS, GET_ORDER, GET_ORDERS_LIST, GET_ORDER_HISTORY, GET_ORDER_SUMMARY, GET_PAYMENT_METHOD, GET_PAYMENT_METHOD_LIST, GET_PAYMENT_METHOD_OPERATIONS, GET_PENDING_SEARCH_INDEX_UPDATES, GET_PRODUCT_LIST, GET_PRODUCT_OPTION_GROUP, GET_PRODUCT_OPTION_GROUPS, GET_PRODUCT_SIMPLE, GET_PRODUCT_VARIANT, GET_PRODUCT_VARIANT_LIST, GET_PRODUCT_VARIANT_LIST_SIMPLE, GET_PRODUCT_VARIANT_OPTIONS, GET_PRODUCT_WITH_VARIANTS, GET_PROMOTION, GET_PROMOTION_LIST, GET_ROLE, GET_ROLES, GET_SERVER_CONFIG, GET_SHIPPING_METHOD, GET_SHIPPING_METHOD_LIST, GET_SHIPPING_METHOD_OPERATIONS, GET_TAG, GET_TAG_LIST, GET_TAX_CATEGORIES, GET_TAX_CATEGORY, GET_TAX_RATE, GET_TAX_RATE_LIST, GET_TAX_RATE_LIST_SIMPLE, GET_UI_STATE, GET_USER_STATUS, GET_ZONE, GET_ZONES, GLOBAL_SETTINGS_FRAGMENT, GlobalFlag, HasPermissionPipe, HealthCheckService, HelpTooltipComponent, HistoryEntryDetailComponent, HistoryEntryType, HttpLoaderFactory, I18nService, INT_CUSTOM_FIELD_FRAGMENT, IfDefaultChannelActiveDirective, IfDirectiveBase, IfMultichannelDirective, IfPermissionsDirective, InjectableTranslateMessageFormatCompiler, ItemsPerPageControlsComponent, JOB_INFO_FRAGMENT, JobQueueService, JobState, JsonEditorFormInputComponent, LOCALE_STRING_CUSTOM_FIELD_FRAGMENT, LOG_OUT, LabeledDataComponent, LanguageCode, LanguageSelectorComponent, LinkDialogComponent, LocalStorageService, LocaleBasePipe, LocaleCurrencyNamePipe, LocaleCurrencyPipe, LocaleDatePipe, LocaleLanguageNamePipe, LocaleRegionNamePipe, LogicalOperator, MODIFY_ORDER, MOVE_COLLECTION, MainNavComponent, ManageTagsDialogComponent, ModalDialogComponent, ModalService, NavBuilderService, NotificationComponent, NotificationService, NumberFormInputComponent, ORDER_ADDRESS_FRAGMENT, ORDER_DETAIL_FRAGMENT, ORDER_FRAGMENT, ORDER_LINE_FRAGMENT, ObjectTreeComponent, OmitTypenameLink, OrderDataService, OrderStateLabelComponent, OverlayHostComponent, OverlayHostService, PAYMENT_METHOD_FRAGMENT, PREVIEW_COLLECTION_CONTENTS, PRODUCT_DETAIL_FRAGMENT, PRODUCT_OPTION_FRAGMENT, PRODUCT_OPTION_GROUP_FRAGMENT, PRODUCT_OPTION_GROUP_WITH_OPTIONS_FRAGMENT, PRODUCT_SELECTOR_SEARCH, PRODUCT_VARIANT_FRAGMENT, PROMOTION_FRAGMENT, PaginationControlsComponent, PasswordFormInputComponent, PercentageSuffixInputComponent, Permission, ProductDataService, ProductSelectorFormInputComponent, ProductVariantSelectorComponent, PromotionDataService, ProsemirrorService, QueryResult, REFUND_FRAGMENT, REFUND_ORDER, REINDEX, RELATION_CUSTOM_FIELD_FRAGMENT, REMOVE_CUSTOMERS_FROM_GROUP, REMOVE_MEMBERS_FROM_ZONE, REMOVE_OPTION_GROUP_FROM_PRODUCT, REMOVE_PRODUCTS_FROM_CHANNEL, REMOVE_VARIANTS_FROM_CHANNEL, REQUEST_COMPLETED, REQUEST_STARTED, ROLE_FRAGMENT, RUN_PENDING_SEARCH_INDEX_UPDATES, RelationAssetInputComponent, RelationCardComponent, RelationCardDetailDirective, RelationCardPreviewDirective, RelationCustomerInputComponent, RelationFormInputComponent, RelationGenericInputComponent, RelationProductInputComponent, RelationProductVariantInputComponent, RelationSelectorDialogComponent, RichTextEditorComponent, RichTextFormInputComponent, SEARCH_PRODUCTS, SETTLE_PAYMENT, SETTLE_REFUND, SET_ACTIVE_CHANNEL, SET_AS_LOGGED_IN, SET_AS_LOGGED_OUT, SET_CONTENT_LANGUAGE, SET_DISPLAY_UI_EXTENSION_POINTS, SET_UI_LANGUAGE_AND_LOCALE, SET_UI_LOCALE, SET_UI_THEME, SHIPPING_METHOD_FRAGMENT, STRING_CUSTOM_FIELD_FRAGMENT, SelectFormInputComponent, SelectToggleComponent, SentenceCasePipe, ServerConfigService, SettingsDataService, SharedModule, ShippingMethodDataService, SimpleDialogComponent, SingleSearchSelectionModel, SingleSearchSelectionModelFactory, SortOrder, SortPipe, StateI18nTokenPipe, StatusBadgeComponent, StockMovementType, StringToColorPipe, TAG_FRAGMENT, TAX_CATEGORY_FRAGMENT, TAX_RATE_FRAGMENT, TEST_ELIGIBLE_SHIPPING_METHODS, TEST_SHIPPING_METHOD, TEXT_CUSTOM_FIELD_FRAGMENT, TRANSITION_FULFILLMENT_TO_STATE, TRANSITION_ORDER_TO_STATE, TRANSITION_PAYMENT_TO_STATE, TabbedCustomFieldsComponent, TableRowActionComponent, TagSelectorComponent, TextFormInputComponent, TextareaFormInputComponent, ThemeSwitcherComponent, TimeAgoPipe, TimelineEntryComponent, TitleInputComponent, UPDATE_ACTIVE_ADMINISTRATOR, UPDATE_ADMINISTRATOR, UPDATE_ASSET, UPDATE_CHANNEL, UPDATE_COLLECTION, UPDATE_COUNTRY, UPDATE_CUSTOMER, UPDATE_CUSTOMER_ADDRESS, UPDATE_CUSTOMER_GROUP, UPDATE_CUSTOMER_NOTE, UPDATE_FACET, UPDATE_FACET_VALUES, UPDATE_GLOBAL_SETTINGS, UPDATE_ORDER_CUSTOM_FIELDS, UPDATE_ORDER_NOTE, UPDATE_PAYMENT_METHOD, UPDATE_PRODUCT, UPDATE_PRODUCT_OPTION, UPDATE_PRODUCT_OPTION_GROUP, UPDATE_PRODUCT_VARIANTS, UPDATE_PROMOTION, UPDATE_ROLE, UPDATE_SHIPPING_METHOD, UPDATE_TAG, UPDATE_TAX_CATEGORY, UPDATE_TAX_RATE, UPDATE_USER_CHANNELS, UPDATE_ZONE, USER_STATUS_FRAGMENT, UiExtensionPointComponent, UiLanguageSwitcherDialogComponent, UserMenuComponent, ZONE_FRAGMENT, addActionBarItem, addCustomFields, addNavMenuItem, addNavMenuSection, blockQuoteRule, buildInputRules, buildKeymap, buildMenuItems, bulletListRule, canInsert, clientResolvers, codeBlockRule, configurableDefinitionToInstance, configurableOperationValueIsValid, createApollo, createResolveData, createUpdatedTranslatable, dayOfWeekIndex, defaultFormInputs, detailBreadcrumb, encodeConfigArgValue, findTranslation, flattenFacetValues, getAppConfig, getClientDefaults, getConfigArgValue, getDefaultConfigArgValue, getDefaultUiLanguage, getDefaultUiLocale, getLocales, getMarkRange, getServerLocation, headingRule, hostExternalFrame, initializeServerConfigService, insertImageItem, interpolateDescription, result as introspectionResult, isEntityCreateOrUpdateMutation, jsonValidator, linkItem, linkSelectPlugin, loadAppConfig, markActive, orderedListRule, registerCustomDetailComponent, registerCustomFieldComponent, registerDashboardWidget, registerDefaultFormInputs, registerFormInputComponent, removeReadonlyCustomFields, setDashboardWidgetLayout, stringToColor, toConfigurableOperationInput, transformRelationCustomFieldInputs, unicodePatternValidator, weekDayNames };
16560
+ export { ADDRESS_FRAGMENT, ADD_CUSTOMERS_TO_GROUP, ADD_MANUAL_PAYMENT_TO_ORDER, ADD_MEMBERS_TO_ZONE, ADD_NOTE_TO_CUSTOMER, ADD_NOTE_TO_ORDER, ADD_OPTION_GROUP_TO_PRODUCT, ADD_OPTION_TO_GROUP, ADMINISTRATOR_FRAGMENT, ADMIN_UI_VERSION, ALL_CUSTOM_FIELDS_FRAGMENT, ASSET_FRAGMENT, ASSIGN_PRODUCTS_TO_CHANNEL, ASSIGN_ROLE_TO_ADMINISTRATOR, ASSIGN_VARIANTS_TO_CHANNEL, ATTEMPT_LOGIN, AUTH_REDIRECT_PARAM, ActionBarComponent, ActionBarItemsComponent, ActionBarLeftComponent, ActionBarRightComponent, AddressFormComponent, AdjustmentType, AdministratorDataService, AffixedInputComponent, AppComponent, AppComponentModule, AppShellComponent, AssetFileInputComponent, AssetGalleryComponent, AssetPickerDialogComponent, AssetPreviewComponent, AssetPreviewDialogComponent, AssetPreviewLinksComponent, AssetPreviewPipe, AssetSearchInputComponent, AssetType, AuthDataService, AuthGuard, AuthService, BOOLEAN_CUSTOM_FIELD_FRAGMENT, BaseDataService, BaseDetailComponent, BaseEntityResolver, BaseListComponent, BooleanFormInputComponent, BreadcrumbComponent, CANCEL_JOB, CANCEL_ORDER, CHANNEL_FRAGMENT, COLLECTION_FRAGMENT, CONFIGURABLE_OPERATION_DEF_FRAGMENT, CONFIGURABLE_OPERATION_FRAGMENT, COUNTRY_FRAGMENT, CREATE_ADMINISTRATOR, CREATE_ASSETS, CREATE_CHANNEL, CREATE_COLLECTION, CREATE_COUNTRY, CREATE_CUSTOMER, CREATE_CUSTOMER_ADDRESS, CREATE_CUSTOMER_GROUP, CREATE_FACET, CREATE_FACET_VALUES, CREATE_FULFILLMENT, CREATE_PAYMENT_METHOD, CREATE_PRODUCT, CREATE_PRODUCT_OPTION_GROUP, CREATE_PRODUCT_VARIANTS, CREATE_PROMOTION, CREATE_ROLE, CREATE_SHIPPING_METHOD, CREATE_TAG, CREATE_TAX_CATEGORY, CREATE_TAX_RATE, CREATE_ZONE, CURRENT_USER_FRAGMENT, CUSTOMER_FRAGMENT, CUSTOMER_GROUP_FRAGMENT, CUSTOM_FIELD_CONFIG_FRAGMENT, CanDeactivateDetailGuard, ChannelAssignmentControlComponent, ChannelBadgeComponent, ChannelLabelPipe, ChannelSwitcherComponent, CheckJobsLink, ChipComponent, ClientDataService, CollectionDataService, CombinationModeFormInputComponent, ComponentRegistryService, ConfigurableInputComponent, CoreModule, CurrencyCode, CurrencyFormInputComponent, CurrencyInputComponent, CustomDetailComponentHostComponent, CustomDetailComponentService, CustomFieldComponentService, CustomFieldControlComponent, CustomFieldLabelPipe, CustomHttpTranslationLoader, CustomerDataService, CustomerGroupFormInputComponent, CustomerLabelComponent, DATE_TIME_CUSTOM_FIELD_FRAGMENT, DELETE_ADMINISTRATOR, DELETE_ASSETS, DELETE_CHANNEL, DELETE_COLLECTION, DELETE_COUNTRY, DELETE_CUSTOMER, DELETE_CUSTOMER_ADDRESS, DELETE_CUSTOMER_GROUP, DELETE_CUSTOMER_NOTE, DELETE_FACET, DELETE_FACET_VALUES, DELETE_ORDER_NOTE, DELETE_PAYMENT_METHOD, DELETE_PRODUCT, DELETE_PRODUCT_VARIANT, DELETE_PROMOTION, DELETE_ROLE, DELETE_SHIPPING_METHOD, DELETE_TAG, DELETE_TAX_CATEGORY, DELETE_TAX_RATE, DELETE_ZONE, DISCOUNT_FRAGMENT, DashboardWidgetService, DataModule, DataService, DataTableColumnComponent, DataTableComponent, DateFormInputComponent, DatetimePickerComponent, DatetimePickerService, DefaultInterceptor, DeletionResult, DialogButtonsDirective, DialogComponentOutletComponent, DialogTitleDirective, DisabledDirective, DropdownComponent, DropdownItemDirective, DropdownMenuComponent, DropdownTriggerDirective, DurationPipe, DynamicFormInputComponent, ERROR_RESULT_FRAGMENT, EditNoteDialogComponent, EmptyPlaceholderComponent, EntityInfoComponent, ErrorCode, ExtensionHostComponent, ExtensionHostConfig, ExtensionHostService, ExternalImageDialogComponent, FACET_VALUE_FRAGMENT, FACET_WITH_VALUES_FRAGMENT, FLOAT_CUSTOM_FIELD_FRAGMENT, FULFILLMENT_FRAGMENT, FacetDataService, FacetValueChipComponent, FacetValueFormInputComponent, FacetValueSelectorComponent, FetchAdapter, FileSizePipe, FocalPointControlComponent, FormFieldComponent, FormFieldControlDirective, FormItemComponent, FormattedAddressComponent, GET_ACTIVE_ADMINISTRATOR, GET_ACTIVE_CHANNEL, GET_ADJUSTMENT_OPERATIONS, GET_ADMINISTRATOR, GET_ADMINISTRATORS, GET_ASSET, GET_ASSET_LIST, GET_AVAILABLE_COUNTRIES, GET_CHANNEL, GET_CHANNELS, GET_CLIENT_STATE, GET_COLLECTION, GET_COLLECTION_CONTENTS, GET_COLLECTION_FILTERS, GET_COLLECTION_LIST, GET_COUNTRY, GET_COUNTRY_LIST, GET_CURRENT_USER, GET_CUSTOMER, GET_CUSTOMER_GROUPS, GET_CUSTOMER_GROUP_WITH_CUSTOMERS, GET_CUSTOMER_HISTORY, GET_CUSTOMER_LIST, GET_FACET_LIST, GET_FACET_WITH_VALUES, GET_GLOBAL_SETTINGS, GET_JOBS_BY_ID, GET_JOBS_LIST, GET_JOB_INFO, GET_JOB_QUEUE_LIST, GET_NEWTORK_STATUS, GET_ORDER, GET_ORDERS_LIST, GET_ORDER_HISTORY, GET_ORDER_SUMMARY, GET_PAYMENT_METHOD, GET_PAYMENT_METHOD_LIST, GET_PAYMENT_METHOD_OPERATIONS, GET_PENDING_SEARCH_INDEX_UPDATES, GET_PRODUCT_LIST, GET_PRODUCT_OPTION_GROUP, GET_PRODUCT_OPTION_GROUPS, GET_PRODUCT_SIMPLE, GET_PRODUCT_VARIANT, GET_PRODUCT_VARIANT_LIST, GET_PRODUCT_VARIANT_LIST_SIMPLE, GET_PRODUCT_VARIANT_OPTIONS, GET_PRODUCT_WITH_VARIANTS, GET_PROMOTION, GET_PROMOTION_LIST, GET_ROLE, GET_ROLES, GET_SERVER_CONFIG, GET_SHIPPING_METHOD, GET_SHIPPING_METHOD_LIST, GET_SHIPPING_METHOD_OPERATIONS, GET_TAG, GET_TAG_LIST, GET_TAX_CATEGORIES, GET_TAX_CATEGORY, GET_TAX_RATE, GET_TAX_RATE_LIST, GET_TAX_RATE_LIST_SIMPLE, GET_UI_STATE, GET_USER_STATUS, GET_ZONE, GET_ZONES, GLOBAL_SETTINGS_FRAGMENT, GlobalFlag, HasPermissionPipe, HealthCheckService, HelpTooltipComponent, HistoryEntryDetailComponent, HistoryEntryType, HttpLoaderFactory, I18nService, INT_CUSTOM_FIELD_FRAGMENT, IfDefaultChannelActiveDirective, IfDirectiveBase, IfMultichannelDirective, IfPermissionsDirective, InjectableTranslateMessageFormatCompiler, ItemsPerPageControlsComponent, JOB_INFO_FRAGMENT, JobQueueService, JobState, JsonEditorFormInputComponent, LOCALE_STRING_CUSTOM_FIELD_FRAGMENT, LOG_OUT, LabeledDataComponent, LanguageCode, LanguageSelectorComponent, LinkDialogComponent, LocalStorageService, LocaleBasePipe, LocaleCurrencyNamePipe, LocaleCurrencyPipe, LocaleDatePipe, LocaleLanguageNamePipe, LocaleRegionNamePipe, LogicalOperator, MODIFY_ORDER, MOVE_COLLECTION, MainNavComponent, ManageTagsDialogComponent, ModalDialogComponent, ModalService, NavBuilderService, NotificationComponent, NotificationService, NumberFormInputComponent, ORDER_ADDRESS_FRAGMENT, ORDER_DETAIL_FRAGMENT, ORDER_FRAGMENT, ORDER_LINE_FRAGMENT, ObjectTreeComponent, OmitTypenameLink, OrderDataService, OrderStateLabelComponent, OverlayHostComponent, OverlayHostService, PAYMENT_METHOD_FRAGMENT, PREVIEW_COLLECTION_CONTENTS, PRODUCT_DETAIL_FRAGMENT, PRODUCT_OPTION_FRAGMENT, PRODUCT_OPTION_GROUP_FRAGMENT, PRODUCT_OPTION_GROUP_WITH_OPTIONS_FRAGMENT, PRODUCT_SELECTOR_SEARCH, PRODUCT_VARIANT_FRAGMENT, PROMOTION_FRAGMENT, PaginationControlsComponent, PasswordFormInputComponent, PercentageSuffixInputComponent, Permission, ProductDataService, ProductMultiSelectorDialogComponent, ProductMultiSelectorFormInputComponent, ProductSearchInputComponent, ProductSelectorFormInputComponent, ProductVariantSelectorComponent, PromotionDataService, ProsemirrorService, QueryResult, REFUND_FRAGMENT, REFUND_ORDER, REINDEX, RELATION_CUSTOM_FIELD_FRAGMENT, REMOVE_CUSTOMERS_FROM_GROUP, REMOVE_MEMBERS_FROM_ZONE, REMOVE_OPTION_GROUP_FROM_PRODUCT, REMOVE_PRODUCTS_FROM_CHANNEL, REMOVE_VARIANTS_FROM_CHANNEL, REQUEST_COMPLETED, REQUEST_STARTED, ROLE_FRAGMENT, RUN_PENDING_SEARCH_INDEX_UPDATES, RelationAssetInputComponent, RelationCardComponent, RelationCardDetailDirective, RelationCardPreviewDirective, RelationCustomerInputComponent, RelationFormInputComponent, RelationGenericInputComponent, RelationProductInputComponent, RelationProductVariantInputComponent, RelationSelectorDialogComponent, RichTextEditorComponent, RichTextFormInputComponent, SEARCH_PRODUCTS, SETTLE_PAYMENT, SETTLE_REFUND, SET_ACTIVE_CHANNEL, SET_AS_LOGGED_IN, SET_AS_LOGGED_OUT, SET_CONTENT_LANGUAGE, SET_DISPLAY_UI_EXTENSION_POINTS, SET_UI_LANGUAGE_AND_LOCALE, SET_UI_LOCALE, SET_UI_THEME, SHIPPING_METHOD_FRAGMENT, STRING_CUSTOM_FIELD_FRAGMENT, SelectFormInputComponent, SelectToggleComponent, SelectionManager, SentenceCasePipe, ServerConfigService, SettingsDataService, SharedModule, ShippingMethodDataService, SimpleDialogComponent, SingleSearchSelectionModel, SingleSearchSelectionModelFactory, SortOrder, SortPipe, StateI18nTokenPipe, StatusBadgeComponent, StockMovementType, StringToColorPipe, TAG_FRAGMENT, TAX_CATEGORY_FRAGMENT, TAX_RATE_FRAGMENT, TEST_ELIGIBLE_SHIPPING_METHODS, TEST_SHIPPING_METHOD, TEXT_CUSTOM_FIELD_FRAGMENT, TRANSITION_FULFILLMENT_TO_STATE, TRANSITION_ORDER_TO_STATE, TRANSITION_PAYMENT_TO_STATE, TabbedCustomFieldsComponent, TableRowActionComponent, TagSelectorComponent, TextFormInputComponent, TextareaFormInputComponent, ThemeSwitcherComponent, TimeAgoPipe, TimelineEntryComponent, TitleInputComponent, UPDATE_ACTIVE_ADMINISTRATOR, UPDATE_ADMINISTRATOR, UPDATE_ASSET, UPDATE_CHANNEL, UPDATE_COLLECTION, UPDATE_COUNTRY, UPDATE_CUSTOMER, UPDATE_CUSTOMER_ADDRESS, UPDATE_CUSTOMER_GROUP, UPDATE_CUSTOMER_NOTE, UPDATE_FACET, UPDATE_FACET_VALUES, UPDATE_GLOBAL_SETTINGS, UPDATE_ORDER_CUSTOM_FIELDS, UPDATE_ORDER_NOTE, UPDATE_PAYMENT_METHOD, UPDATE_PRODUCT, UPDATE_PRODUCT_OPTION, UPDATE_PRODUCT_OPTION_GROUP, UPDATE_PRODUCT_VARIANTS, UPDATE_PROMOTION, UPDATE_ROLE, UPDATE_SHIPPING_METHOD, UPDATE_TAG, UPDATE_TAX_CATEGORY, UPDATE_TAX_RATE, UPDATE_USER_CHANNELS, UPDATE_ZONE, USER_STATUS_FRAGMENT, UiExtensionPointComponent, UiLanguageSwitcherDialogComponent, UserMenuComponent, ZONE_FRAGMENT, addActionBarItem, addCustomFields, addNavMenuItem, addNavMenuSection, blockQuoteRule, buildInputRules, buildKeymap, buildMenuItems, bulletListRule, canInsert, clientResolvers, codeBlockRule, configurableDefinitionToInstance, configurableOperationValueIsValid, createApollo, createResolveData, createUpdatedTranslatable, dayOfWeekIndex, defaultFormInputs, detailBreadcrumb, encodeConfigArgValue, findTranslation, flattenFacetValues, getAppConfig, getClientDefaults, getConfigArgValue, getDefaultConfigArgValue, getDefaultUiLanguage, getDefaultUiLocale, getLocales, getMarkRange, getServerLocation, headingRule, hostExternalFrame, initializeServerConfigService, insertImageItem, interpolateDescription, result as introspectionResult, isEntityCreateOrUpdateMutation, jsonValidator, linkItem, linkSelectPlugin, loadAppConfig, markActive, orderedListRule, registerCustomDetailComponent, registerCustomFieldComponent, registerDashboardWidget, registerDefaultFormInputs, registerFormInputComponent, removeReadonlyCustomFields, setDashboardWidgetLayout, stringToColor, toConfigurableOperationInput, transformRelationCustomFieldInputs, unicodePatternValidator, weekDayNames };
16186
16561
  //# sourceMappingURL=vendure-admin-ui-core.mjs.map