@aquera/nile-elements 2.0.18 → 2.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/demo/index.js +0 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1275 -490
- package/dist/nile-badge/index.cjs.js +1 -1
- package/dist/nile-badge/index.esm.js +1 -1
- package/dist/nile-badge/nile-badge.cjs.js +1 -1
- package/dist/nile-badge/nile-badge.cjs.js.map +1 -1
- package/dist/nile-badge/nile-badge.css.cjs.js +1 -1
- package/dist/nile-badge/nile-badge.css.cjs.js.map +1 -1
- package/dist/nile-badge/nile-badge.css.esm.js +24 -3
- package/dist/nile-badge/nile-badge.esm.js +5 -3
- package/dist/nile-breadcrumb/nile-breadcrumb.cjs.js +1 -1
- package/dist/nile-breadcrumb/nile-breadcrumb.cjs.js.map +1 -1
- package/dist/nile-breadcrumb/nile-breadcrumb.esm.js +2 -2
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.cjs.js +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.cjs.js.map +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.css.cjs.js +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.css.cjs.js.map +1 -1
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.css.esm.js +14 -2
- package/dist/nile-breadcrumb-item/nile-breadcrumb-item.esm.js +4 -4
- package/dist/nile-calendar/index.cjs.js +1 -1
- package/dist/nile-calendar/index.esm.js +1 -1
- package/dist/nile-calendar/nile-calendar.cjs.js +2 -1
- package/dist/nile-calendar/nile-calendar.cjs.js.map +1 -1
- package/dist/nile-calendar/nile-calendar.css.cjs.js +1 -1
- package/dist/nile-calendar/nile-calendar.css.cjs.js.map +1 -1
- package/dist/nile-calendar/nile-calendar.css.esm.js +357 -2
- package/dist/nile-calendar/nile-calendar.esm.js +365 -41
- package/dist/nile-calendar/timezones.cjs.js +1 -1
- package/dist/nile-calendar/timezones.cjs.js.map +1 -1
- package/dist/nile-calendar/timezones.esm.js +1 -1
- package/dist/nile-date-time-picker/index.cjs.js +2 -0
- package/dist/nile-date-time-picker/index.cjs.js.map +1 -0
- package/dist/nile-date-time-picker/index.esm.js +1 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.cjs.js +2 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.cjs.js.map +1 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.css.cjs.js +2 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.css.cjs.js.map +1 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.css.esm.js +13 -0
- package/dist/nile-date-time-picker/nile-date-time-picker.esm.js +53 -0
- package/dist/nile-select/index.cjs.js +1 -1
- package/dist/nile-select/index.esm.js +1 -1
- package/dist/nile-select/nile-select.cjs.js +2 -2
- package/dist/nile-select/nile-select.cjs.js.map +1 -1
- package/dist/nile-select/nile-select.esm.js +1 -1
- package/dist/nile-select/virtual-scroll-helper.cjs.js +1 -1
- package/dist/nile-select/virtual-scroll-helper.cjs.js.map +1 -1
- package/dist/nile-select/virtual-scroll-helper.esm.js +48 -47
- package/dist/nile-virtual-select/nile-virtual-select.cjs.js +4 -4
- package/dist/nile-virtual-select/nile-virtual-select.cjs.js.map +1 -1
- package/dist/nile-virtual-select/nile-virtual-select.esm.js +2 -2
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/nile-badge/nile-badge.css.js +24 -3
- package/dist/src/nile-badge/nile-badge.css.js.map +1 -1
- package/dist/src/nile-badge/nile-badge.d.ts +7 -4
- package/dist/src/nile-badge/nile-badge.js +22 -5
- package/dist/src/nile-badge/nile-badge.js.map +1 -1
- package/dist/src/nile-badge/nile-badge.test.js +88 -0
- package/dist/src/nile-badge/nile-badge.test.js.map +1 -1
- package/dist/src/nile-breadcrumb/nile-breadcrumb.d.ts +7 -0
- package/dist/src/nile-breadcrumb/nile-breadcrumb.js +24 -1
- package/dist/src/nile-breadcrumb/nile-breadcrumb.js.map +1 -1
- package/dist/src/nile-breadcrumb/nile-breadcrumb.test.js +51 -0
- package/dist/src/nile-breadcrumb/nile-breadcrumb.test.js.map +1 -1
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.css.js +12 -0
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.css.js.map +1 -1
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.d.ts +5 -0
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.js +9 -0
- package/dist/src/nile-breadcrumb-item/nile-breadcrumb-item.js.map +1 -1
- package/dist/src/nile-calendar/nile-calendar.css.js +355 -0
- package/dist/src/nile-calendar/nile-calendar.css.js.map +1 -1
- package/dist/src/nile-calendar/nile-calendar.d.ts +175 -0
- package/dist/src/nile-calendar/nile-calendar.js +1726 -26
- package/dist/src/nile-calendar/nile-calendar.js.map +1 -1
- package/dist/src/nile-calendar/nile-calendar.test.d.ts +1 -0
- package/dist/src/nile-calendar/nile-calendar.test.js +3580 -0
- package/dist/src/nile-calendar/nile-calendar.test.js.map +1 -1
- package/dist/src/nile-calendar/timezones.d.ts +21 -0
- package/dist/src/nile-calendar/timezones.js +49 -0
- package/dist/src/nile-calendar/timezones.js.map +1 -1
- package/dist/src/nile-date-time-picker/index.d.ts +1 -0
- package/dist/src/nile-date-time-picker/index.js +2 -0
- package/dist/src/nile-date-time-picker/index.js.map +1 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.css.d.ts +11 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.css.js +49 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.css.js.map +1 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.d.ts +173 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.js +1270 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.js.map +1 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.test.d.ts +143 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.test.js +7277 -0
- package/dist/src/nile-date-time-picker/nile-date-time-picker.test.js.map +1 -0
- package/dist/src/nile-select/nile-select.d.ts +1 -0
- package/dist/src/nile-select/nile-select.js +16 -1
- package/dist/src/nile-select/nile-select.js.map +1 -1
- package/dist/src/nile-select/nile-select.test.js +430 -5
- package/dist/src/nile-select/nile-select.test.js.map +1 -1
- package/dist/src/nile-select/virtual-scroll-helper.js +7 -4
- package/dist/src/nile-select/virtual-scroll-helper.js.map +1 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.d.ts +3 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.js +14 -6
- package/dist/src/nile-virtual-select/nile-virtual-select.js.map +1 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.test.js +115 -1
- package/dist/src/nile-virtual-select/nile-virtual-select.test.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/animation-registry.cjs.js +1 -1
- package/dist/utilities/animation-registry.cjs.js.map +1 -1
- package/dist/utilities/animation-registry.esm.js +1 -1
- package/package.json +3 -1
- package/scripts/coverage-report.mjs +96 -0
- package/src/index.ts +1 -0
- package/src/nile-badge/nile-badge.css.ts +24 -3
- package/src/nile-badge/nile-badge.test.ts +102 -0
- package/src/nile-badge/nile-badge.ts +28 -5
- package/src/nile-breadcrumb/nile-breadcrumb.test.ts +57 -0
- package/src/nile-breadcrumb/nile-breadcrumb.ts +19 -0
- package/src/nile-breadcrumb-item/nile-breadcrumb-item.css.ts +12 -0
- package/src/nile-breadcrumb-item/nile-breadcrumb-item.ts +7 -0
- package/src/nile-calendar/nile-calendar.css.ts +355 -0
- package/src/nile-calendar/nile-calendar.test.ts +3793 -0
- package/src/nile-calendar/nile-calendar.ts +1760 -28
- package/src/nile-calendar/timezones.ts +57 -0
- package/src/nile-date-time-picker/index.ts +1 -0
- package/src/nile-date-time-picker/nile-date-time-picker.css.ts +54 -0
- package/src/nile-date-time-picker/nile-date-time-picker.test.ts +7886 -0
- package/src/nile-date-time-picker/nile-date-time-picker.ts +1153 -0
- package/src/nile-select/nile-select.test.ts +560 -5
- package/src/nile-select/nile-select.ts +21 -1
- package/src/nile-select/virtual-scroll-helper.ts +7 -4
- package/src/nile-virtual-select/nile-virtual-select.test.ts +139 -1
- package/src/nile-virtual-select/nile-virtual-select.ts +17 -6
- package/vscode-html-custom-data.json +200 -20
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
System.register([],function(_export,_context){"use strict";var n,t;function o(
|
|
1
|
+
System.register([],function(_export,_context){"use strict";var n,t;function _typeof(o){"@babel/helpers - typeof";return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o;}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o;},_typeof(o);}function ownKeys(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);r&&(o=o.filter(function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable;})),t.push.apply(t,o);}return t;}function _objectSpread(e){for(var r=1;r<arguments.length;r++){var t=null!=arguments[r]?arguments[r]:{};r%2?ownKeys(Object(t),!0).forEach(function(r){_defineProperty(e,r,t[r]);}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):ownKeys(Object(t)).forEach(function(r){Object.defineProperty(e,r,Object.getOwnPropertyDescriptor(t,r));});}return e;}function _defineProperty(e,r,t){return(r=_toPropertyKey(r))in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e;}function _toPropertyKey(t){var i=_toPrimitive(t,"string");return"symbol"==_typeof(i)?i:i+"";}function _toPrimitive(t,r){if("object"!=_typeof(t)||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var i=e.call(t,r||"default");if("object"!=_typeof(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.");}return("string"===r?String:Number)(t);}function o(n){return n!==null&&n!==void 0?n:{keyframes:[],options:{duration:0}};}function r(n,t){return"rtl"===t.toLowerCase()?{keyframes:n.rtlKeyframes||n.keyframes,options:n.options}:n;}function e(t,r){n.set(t,o(r));}function s(n,r,e){t.set(n,_objectSpread(_objectSpread({},t.get(n)),{},_defineProperty({},r,o(e))));}function a(o,e,s){var a=t.get(o);if(a!==null&&a!==void 0&&a[e])return r(a[e],s.dir);var i=n.get(e);return i?r(i,s.dir):{keyframes:[],options:{duration:0}};}_export({a:s,g:a,s:e});return{setters:[],execute:function execute(){n=new Map(),t=new WeakMap();}};});
|
|
2
2
|
//# sourceMappingURL=animation-registry.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animation-registry.cjs.js","sources":["../../../src/utilities/animation-registry.ts"],"sourcesContent":["export interface ElementAnimation {\n keyframes: Keyframe[];\n rtlKeyframes?: Keyframe[];\n options?: KeyframeAnimationOptions;\n}\n\nexport interface ElementAnimationMap {\n [animationName: string]: ElementAnimation;\n}\n\nexport interface GetAnimationOptions {\n /**\n * The component's directionality. When set to \"rtl\", `rtlKeyframes` will be preferred over `keyframes` where\n * available using getAnimation().\n */\n dir: string;\n}\n\nconst defaultAnimationRegistry = new Map<string, ElementAnimation>();\nconst customAnimationRegistry = new WeakMap<Element, ElementAnimationMap>();\n\nfunction ensureAnimation(animation: ElementAnimation | null) {\n return animation ?? { keyframes: [], options: { duration: 0 } };\n}\n\n//\n// Given an ElementAnimation, this function returns a new ElementAnimation where the keyframes property reflects either\n// keyframes or rtlKeyframes depending on the specified directionality.\n//\nfunction getLogicalAnimation(animation: ElementAnimation, dir: string) {\n if (dir.toLowerCase() === 'rtl') {\n return {\n keyframes: animation.rtlKeyframes || animation.keyframes,\n options: animation.options\n };\n }\n\n return animation;\n}\n\n/**\n * Sets a default animation. Components should use the `name.animation` for primary animations and `name.part.animation`\n * for secondary animations, e.g. `dialog.show` and `dialog.overlay.show`. For modifiers, use `drawer.showTop`.\n */\nexport function setDefaultAnimation(animationName: string, animation: ElementAnimation | null) {\n defaultAnimationRegistry.set(animationName, ensureAnimation(animation));\n}\n\n/** Sets a custom animation for the specified element. */\nexport function setAnimation(el: Element, animationName: string, animation: ElementAnimation | null) {\n customAnimationRegistry.set(el, { ...customAnimationRegistry.get(el), [animationName]: ensureAnimation(animation) });\n}\n\n/** Gets an element's animation. Falls back to the default if no animation is found. */\nexport function getAnimation(el: Element, animationName: string, options: GetAnimationOptions) {\n const customAnimation = customAnimationRegistry.get(el);\n\n // Check for a custom animation\n if (customAnimation?.[animationName]) {\n return getLogicalAnimation(customAnimation[animationName], options.dir);\n }\n\n // Check for a default animation\n const defaultAnimation = defaultAnimationRegistry.get(animationName);\n if (defaultAnimation) {\n return getLogicalAnimation(defaultAnimation, options.dir);\n }\n\n // Fall back to an empty animation\n return {\n keyframes: [],\n options: { duration: 0 }\n };\n}\n"],"names":["
|
|
1
|
+
{"version":3,"file":"animation-registry.cjs.js","sources":["../../../src/utilities/animation-registry.ts"],"sourcesContent":["export interface ElementAnimation {\n keyframes: Keyframe[];\n rtlKeyframes?: Keyframe[];\n options?: KeyframeAnimationOptions;\n}\n\nexport interface ElementAnimationMap {\n [animationName: string]: ElementAnimation;\n}\n\nexport interface GetAnimationOptions {\n /**\n * The component's directionality. When set to \"rtl\", `rtlKeyframes` will be preferred over `keyframes` where\n * available using getAnimation().\n */\n dir: string;\n}\n\nconst defaultAnimationRegistry = new Map<string, ElementAnimation>();\nconst customAnimationRegistry = new WeakMap<Element, ElementAnimationMap>();\n\nfunction ensureAnimation(animation: ElementAnimation | null) {\n return animation ?? { keyframes: [], options: { duration: 0 } };\n}\n\n//\n// Given an ElementAnimation, this function returns a new ElementAnimation where the keyframes property reflects either\n// keyframes or rtlKeyframes depending on the specified directionality.\n//\nfunction getLogicalAnimation(animation: ElementAnimation, dir: string) {\n if (dir.toLowerCase() === 'rtl') {\n return {\n keyframes: animation.rtlKeyframes || animation.keyframes,\n options: animation.options\n };\n }\n\n return animation;\n}\n\n/**\n * Sets a default animation. Components should use the `name.animation` for primary animations and `name.part.animation`\n * for secondary animations, e.g. `dialog.show` and `dialog.overlay.show`. For modifiers, use `drawer.showTop`.\n */\nexport function setDefaultAnimation(animationName: string, animation: ElementAnimation | null) {\n defaultAnimationRegistry.set(animationName, ensureAnimation(animation));\n}\n\n/** Sets a custom animation for the specified element. */\nexport function setAnimation(el: Element, animationName: string, animation: ElementAnimation | null) {\n customAnimationRegistry.set(el, { ...customAnimationRegistry.get(el), [animationName]: ensureAnimation(animation) });\n}\n\n/** Gets an element's animation. Falls back to the default if no animation is found. */\nexport function getAnimation(el: Element, animationName: string, options: GetAnimationOptions) {\n const customAnimation = customAnimationRegistry.get(el);\n\n // Check for a custom animation\n if (customAnimation?.[animationName]) {\n return getLogicalAnimation(customAnimation[animationName], options.dir);\n }\n\n // Check for a default animation\n const defaultAnimation = defaultAnimationRegistry.get(animationName);\n if (defaultAnimation) {\n return getLogicalAnimation(defaultAnimation, options.dir);\n }\n\n // Fall back to an empty animation\n return {\n keyframes: [],\n options: { duration: 0 }\n };\n}\n"],"names":["ensureAnimation","animation","keyframes","options","duration","getLogicalAnimation","dir","toLowerCase","rtlKeyframes","setDefaultAnimation","animationName","defaultAnimationRegistry","set","setAnimation","el","customAnimationRegistry","get","getAnimation","customAnimation","defaultAnimation","Map","WeakMap"],"mappings":"+8CAqBA,QAASA,CAAAA,CAAgBC,CAAAA,CAAAA,CAAAA,CACvB,MAAOA,CAAAA,CAAAA,SAAAA,CAAAA,UAAAA,CAAAA,CAAa,CAAEC,SAAW,CAAA,EAAA,CAAIC,OAAS,CAAA,CAAEC,QAAU,CAAA,CAAA,CAAA,CAC5D,EAMA,QAASC,CAAAA,CAAAA,CAAoBJ,CAA6BK,CAAAA,CAAAA,CAAAA,CACxD,MAA0B,KAAA,GAAtBA,EAAIC,WACC,CAAA,CAAA,CAAA,CACLL,UAAWD,CAAUO,CAAAA,YAAAA,EAAgBP,EAAUC,SAC/CC,CAAAA,OAAAA,CAASF,CAAUE,CAAAA,OAAAA,CAAAA,CAIhBF,CACT,EAMgB,QAAAQ,CAAAA,CAAoBC,CAAAA,CAAAA,CAAuBT,CACzDU,CAAAA,CAAAA,CAAAA,CAAyBC,GAAIF,CAAAA,CAAAA,CAAeV,EAAgBC,CAC9D,CAAA,CAAA,UAGgBY,CAAAA,CAAAA,CAAaC,CAAaJ,CAAAA,CAAAA,CAAuBT,GAC/Dc,CAAwBH,CAAAA,GAAAA,CAAIE,iCAASC,CAAAA,CAAwBC,IAAIF,CAAKJ,CAAAA,KAAAA,eAAAA,IAACA,CAAgBV,CAAAA,CAAAA,CAAgBC,CACzG,CAAA,EAAA,CAAA,UAGgBgB,CAAAA,CAAaH,CAAAA,CAAAA,CAAaJ,CAAuBP,CAAAA,CAAAA,CAAAA,CAC/D,GAAMe,CAAAA,CAAAA,CAAkBH,EAAwBC,GAAIF,CAAAA,CAAAA,CAAAA,CAGpD,GAAII,CAAAA,SAAAA,CAAAA,WAAAA,CAAAA,CAAkBR,CACpB,CAAA,CAAA,MAAOL,CAAAA,EAAoBa,CAAgBR,CAAAA,CAAAA,CAAAA,CAAgBP,EAAQG,GAIrE,CAAA,CAAA,GAAMa,CAAAA,EAAmBR,CAAyBK,CAAAA,GAAAA,CAAIN,CACtD,CAAA,CAAA,MAAIS,CAAAA,CACKd,CAAAA,CAAAA,CAAoBc,EAAkBhB,CAAQG,CAAAA,GAAAA,CAAAA,CAIhD,CACLJ,SAAAA,CAAW,EACXC,CAAAA,OAAAA,CAAS,CAAEC,QAAU,CAAA,CAAA,CAAA,CAEzB,sEAvDMO,CAAAA,CAA2B,GAAIS,CAAAA,GAC/BL,CAAAA,CAAAA,CAAAA,CAAAA,CAA0B,GAAIM,CAAAA,OAEpC,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const n=new Map,t=new WeakMap;function o(n,t){return"rtl"===t.toLowerCase()?{keyframes:n.rtlKeyframes||n.keyframes,options:n.options}:n}function
|
|
1
|
+
const n=new Map,t=new WeakMap;function o(n){return n??{keyframes:[],options:{duration:0}}}function r(n,t){return"rtl"===t.toLowerCase()?{keyframes:n.rtlKeyframes||n.keyframes,options:n.options}:n}function e(t,r){n.set(t,o(r))}function s(n,r,e){t.set(n,{...t.get(n),[r]:o(e)})}function a(o,e,s){const a=t.get(o);if(a?.[e])return r(a[e],s.dir);const i=n.get(e);return i?r(i,s.dir):{keyframes:[],options:{duration:0}}}export{s as a,a as g,e as s};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Webcomponent nile-elements following open-wc recommendations",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "nile-elements",
|
|
6
|
-
"version": "2.0.
|
|
6
|
+
"version": "2.0.20",
|
|
7
7
|
"main": "dist/src/index.js",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"module": "dist/src/index.js",
|
|
@@ -134,6 +134,7 @@
|
|
|
134
134
|
"./nile-color-swatch": "./dist/src/nile-color-swatch/index.js",
|
|
135
135
|
"./nile-tree": "./dist/src/nile-tree/index.js",
|
|
136
136
|
"./nile-tree-item": "./dist/src/nile-tree-item/index.js",
|
|
137
|
+
"./nile-date-time-picker": "./dist/src/nile-date-time-picker/index.js",
|
|
137
138
|
"./nile-wysiwyg-editor": "./dist/src/nile-wysiwyg-editor/index.js",
|
|
138
139
|
"./nile-wysiwyg-toolbar": "./dist/src/nile-wysiwyg-editor/nile-wysiwyg-toolbar/index.js",
|
|
139
140
|
"./nile-app-shell": "./dist/src/nile-app-shell/index.js",
|
|
@@ -197,6 +198,7 @@
|
|
|
197
198
|
"tippy.js": "^6.3.7"
|
|
198
199
|
},
|
|
199
200
|
"devDependencies": {
|
|
201
|
+
"@aquera/nile-glyph": "^1.0.9",
|
|
200
202
|
"@custom-elements-manifest/analyzer": "^0.4.17",
|
|
201
203
|
"@open-wc/eslint-config": "^8.0.2",
|
|
202
204
|
"@open-wc/testing": "^3.1.6",
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Builds coverage.json (consumed by the ui-playground Metrics > Testing tab) from the
|
|
3
|
+
// wtr lcov report, the Istanbul coverage-final.json (statements) and the test runner output.
|
|
4
|
+
// Usage (from a package dir): node scripts/coverage-report.mjs <lcov.info> <test-output.txt> <out.json>
|
|
5
|
+
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
6
|
+
import { execSync } from 'node:child_process';
|
|
7
|
+
import { dirname, join } from 'node:path';
|
|
8
|
+
|
|
9
|
+
const [lcovPath = 'coverage/lcov.info', outputPath, outPath = 'coverage/coverage.json'] = process.argv.slice(2);
|
|
10
|
+
// Run from the package directory (cwd), so this script can be shared by other packages.
|
|
11
|
+
const pkg = JSON.parse(readFileSync('package.json', 'utf8'));
|
|
12
|
+
|
|
13
|
+
const ratio = (covered, total) => ({ covered, total, pct: total ? Math.round((covered / total) * 10000) / 100 : 100 });
|
|
14
|
+
// sMissing counts files without statement data, so a group's statements become null instead of a false 100%.
|
|
15
|
+
const blank = () => ({ files: 0, sMissing: 0, SH: 0, SF: 0, LH: 0, LF: 0, BRH: 0, BRF: 0, FNH: 0, FNF: 0 });
|
|
16
|
+
const relPath = p => p.replace(/\\/g, '/').replace(/^.*?(?:^|\/)src\//, '');
|
|
17
|
+
|
|
18
|
+
// Statements: lcov has no statement metric, so read them from Istanbul's coverage-final.json.
|
|
19
|
+
const statements = new Map();
|
|
20
|
+
const finalPath = join(dirname(lcovPath), 'coverage-final.json');
|
|
21
|
+
try {
|
|
22
|
+
const final = JSON.parse(readFileSync(finalPath, 'utf8'));
|
|
23
|
+
for (const [file, data] of Object.entries(final)) {
|
|
24
|
+
const counts = Object.values(data.s ?? {});
|
|
25
|
+
statements.set(relPath(file), { SH: counts.filter(c => c > 0).length, SF: counts.length });
|
|
26
|
+
}
|
|
27
|
+
} catch (e) {
|
|
28
|
+
statements.clear();
|
|
29
|
+
console.warn(`statements unavailable: cannot read ${finalPath} (${e.code ?? e.message})`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const files = new Map();
|
|
33
|
+
let current = null;
|
|
34
|
+
for (const line of readFileSync(lcovPath, 'utf8').split('\n')) {
|
|
35
|
+
const [key, value] = [line.slice(0, line.indexOf(':')), line.slice(line.indexOf(':') + 1)];
|
|
36
|
+
if (key === 'SF') {
|
|
37
|
+
const rel = relPath(value);
|
|
38
|
+
const st = statements.get(rel);
|
|
39
|
+
current = { ...blank(), ...(st ?? { sMissing: 1 }), files: 1 };
|
|
40
|
+
files.set(rel, current);
|
|
41
|
+
} else if (current && key in current && key !== 'files') {
|
|
42
|
+
current[key] += Number(value) || 0;
|
|
43
|
+
} else if (line === 'end_of_record') {
|
|
44
|
+
current = null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const metrics = g => ({
|
|
49
|
+
statements: g.sMissing ? null : ratio(g.SH, g.SF),
|
|
50
|
+
lines: ratio(g.LH, g.LF),
|
|
51
|
+
branches: ratio(g.BRH, g.BRF),
|
|
52
|
+
functions: ratio(g.FNH, g.FNF),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const groups = new Map();
|
|
56
|
+
const sum = blank();
|
|
57
|
+
const fileRows = [...files].map(([name, g]) => {
|
|
58
|
+
// Only real component folders (src/nile-*/) get a component row; shared code (internal, utilities, slot,
|
|
59
|
+
// version, index) is still in totals and files.
|
|
60
|
+
const group = name.split('/')[0];
|
|
61
|
+
const isComponent = name.includes('/') && group.startsWith('nile-');
|
|
62
|
+
if (isComponent && !groups.has(group)) groups.set(group, blank());
|
|
63
|
+
for (const k of Object.keys(sum)) {
|
|
64
|
+
if (isComponent) groups.get(group)[k] += g[k];
|
|
65
|
+
sum[k] += g[k];
|
|
66
|
+
}
|
|
67
|
+
return { name, ...metrics(g) };
|
|
68
|
+
}).sort((a, b) => a.name.localeCompare(b.name));
|
|
69
|
+
|
|
70
|
+
const components = [...groups].map(([name, g]) => ({ name, files: g.files, ...metrics(g) }))
|
|
71
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
72
|
+
|
|
73
|
+
// null when the counts cannot be parsed, so a broken run is not reported as "0 tests".
|
|
74
|
+
let tests = null;
|
|
75
|
+
if (outputPath && existsSync(outputPath)) {
|
|
76
|
+
const text = readFileSync(outputPath, 'utf8').replace(/\x1B\[[0-9;]*[mK]/g, '');
|
|
77
|
+
const summary = text.split('\n').filter(l => /\d+\s+passed.*\d+\s+failed/.test(l)).pop();
|
|
78
|
+
const passed = summary?.match(/(\d+)\s+passed/)?.[1];
|
|
79
|
+
const failed = summary?.match(/(\d+)\s+failed/)?.[1];
|
|
80
|
+
if (passed !== undefined && failed !== undefined) tests = { passed: Number(passed), failed: Number(failed), total: Number(passed) + Number(failed) };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const git = cmd => { try { return execSync(cmd, { encoding: 'utf8' }).trim(); } catch { return ''; } };
|
|
84
|
+
const report = {
|
|
85
|
+
package: pkg.name,
|
|
86
|
+
version: pkg.version,
|
|
87
|
+
branch: process.env.BITBUCKET_BRANCH || git('git rev-parse --abbrev-ref HEAD'),
|
|
88
|
+
commit: (process.env.BITBUCKET_COMMIT || git('git rev-parse HEAD')).slice(0, 7),
|
|
89
|
+
generatedAt: new Date().toISOString(),
|
|
90
|
+
tests,
|
|
91
|
+
totals: { files: sum.files, ...metrics(sum) },
|
|
92
|
+
components,
|
|
93
|
+
files: fileRows,
|
|
94
|
+
};
|
|
95
|
+
writeFileSync(outPath, JSON.stringify(report, null, 2) + '\n');
|
|
96
|
+
console.log(`coverage.json: ${fileRows.length} files, ${components.length} components, ${report.totals.lines.pct}% lines, ${report.totals.statements ? `${report.totals.statements.pct}%` : 'n/a'} statements, ${tests?.total ?? 'n/a'} tests -> ${outPath}`);
|
package/src/index.ts
CHANGED
|
@@ -154,6 +154,7 @@ export { NileInlineSidebarItemHeader } from './nile-inline-sidebar-item-header';
|
|
|
154
154
|
export { NileInlineSidebarItemBody } from './nile-inline-sidebar-item-body';
|
|
155
155
|
export { NileMarkdown } from './nile-markdown';
|
|
156
156
|
export { NileMarkdownEditor } from './nile-markdown-editor';
|
|
157
|
+
export { NileDateTimePicker } from './nile-date-time-picker';
|
|
157
158
|
|
|
158
159
|
// nile-wysiwyg-editor — ProseMirror-powered rich text editor
|
|
159
160
|
export {
|
|
@@ -27,7 +27,24 @@ export const styles = css`
|
|
|
27
27
|
height: var(--nile-height-22px, var(--ng-height-24px));
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
.
|
|
30
|
+
.badge__prefix,
|
|
31
|
+
.badge__suffix {
|
|
32
|
+
display: inline-flex;
|
|
33
|
+
flex: 0 0 auto;
|
|
34
|
+
align-items: center;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.badge--has-prefix .badge__prefix {
|
|
38
|
+
margin-inline-end: var(--nile-spacing-xs, var(--ng-spacing-xs));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.badge--has-suffix .badge__suffix {
|
|
42
|
+
margin-inline-start: var(--nile-spacing-xs, var(--ng-spacing-xs));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.badge__prefix,
|
|
46
|
+
.badge__content,
|
|
47
|
+
.badge__suffix {
|
|
31
48
|
font-family: var(--nile-font-family-serif, var(--ng-font-family-body));
|
|
32
49
|
font-size: var(--nile-type-scale-2, var(--ng-font-size-text-sm));
|
|
33
50
|
font-style: normal;
|
|
@@ -209,7 +226,9 @@ export const styles = css`
|
|
|
209
226
|
height: var(--nile-height-22px, var(--ng-height-22px));
|
|
210
227
|
}
|
|
211
228
|
|
|
212
|
-
.badge--sm .
|
|
229
|
+
.badge--sm .badge__prefix,
|
|
230
|
+
.badge--sm .badge__content,
|
|
231
|
+
.badge--sm .badge__suffix {
|
|
213
232
|
font-size: var(--nile-type-scale-2, var(--ng-font-size-text-xs));
|
|
214
233
|
line-height: var(--nile-type-scale-5, var(--ng-line-height-text-xs));
|
|
215
234
|
}
|
|
@@ -219,7 +238,9 @@ export const styles = css`
|
|
|
219
238
|
height: var(--nile-height-28px, var(--ng-height-28px));
|
|
220
239
|
}
|
|
221
240
|
|
|
222
|
-
.badge--lg .
|
|
241
|
+
.badge--lg .badge__prefix,
|
|
242
|
+
.badge--lg .badge__content,
|
|
243
|
+
.badge--lg .badge__suffix {
|
|
223
244
|
font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));
|
|
224
245
|
line-height: var(--nile-type-scale-5, var(--ng-line-height-text-sm));
|
|
225
246
|
}
|
|
@@ -744,4 +744,106 @@ describe('NileBadge', () => {
|
|
|
744
744
|
});
|
|
745
745
|
});
|
|
746
746
|
});
|
|
747
|
+
|
|
748
|
+
describe('prefix and suffix slots', () => {
|
|
749
|
+
const base = (el: NileBadge) => el.shadowRoot!.querySelector('[part="base"]')!;
|
|
750
|
+
const slotOf = (el: NileBadge, name: string) =>
|
|
751
|
+
el.shadowRoot!.querySelector<HTMLSlotElement>(`slot[name="${name}"]`)!;
|
|
752
|
+
|
|
753
|
+
it('110. should render prefix and suffix slots with parts', async () => {
|
|
754
|
+
const el = await fixture<NileBadge>(html`<nile-badge>Label</nile-badge>`);
|
|
755
|
+
expect(slotOf(el, 'prefix').getAttribute('part')).to.equal('prefix');
|
|
756
|
+
expect(slotOf(el, 'suffix').getAttribute('part')).to.equal('suffix');
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
it('111. should render prefix before content and suffix after it', async () => {
|
|
760
|
+
const el = await fixture<NileBadge>(html`<nile-badge>Label</nile-badge>`);
|
|
761
|
+
const parts = [...base(el).children].map(n => n.getAttribute('part'));
|
|
762
|
+
expect(parts).to.deep.equal(['prefix', 'content', 'suffix']);
|
|
763
|
+
});
|
|
764
|
+
|
|
765
|
+
it('112. should assign prefix content to the prefix slot', async () => {
|
|
766
|
+
const el = await fixture<NileBadge>(html`<nile-badge><span slot="prefix" id="p">●</span>Label</nile-badge>`);
|
|
767
|
+
const assigned = slotOf(el, 'prefix').assignedElements();
|
|
768
|
+
expect(assigned).to.have.length(1);
|
|
769
|
+
expect(assigned[0].id).to.equal('p');
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
it('113. should assign suffix content to the suffix slot', async () => {
|
|
773
|
+
const el = await fixture<NileBadge>(html`<nile-badge>Label<span slot="suffix" id="s">3</span></nile-badge>`);
|
|
774
|
+
const assigned = slotOf(el, 'suffix').assignedElements();
|
|
775
|
+
expect(assigned).to.have.length(1);
|
|
776
|
+
expect(assigned[0].id).to.equal('s');
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
it('114. should accept any element in the slots', async () => {
|
|
780
|
+
const el = await fixture<NileBadge>(html`
|
|
781
|
+
<nile-badge>
|
|
782
|
+
<img slot="prefix" alt="" />
|
|
783
|
+
Label
|
|
784
|
+
<button slot="suffix">x</button>
|
|
785
|
+
</nile-badge>
|
|
786
|
+
`);
|
|
787
|
+
expect(slotOf(el, 'prefix').assignedElements()[0].tagName).to.equal('IMG');
|
|
788
|
+
expect(slotOf(el, 'suffix').assignedElements()[0].tagName).to.equal('BUTTON');
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
it('115. should not add has-prefix or has-suffix classes when slots are empty', async () => {
|
|
792
|
+
const el = await fixture<NileBadge>(html`<nile-badge>Label</nile-badge>`);
|
|
793
|
+
expect(base(el).classList.contains('badge--has-prefix')).to.be.false;
|
|
794
|
+
expect(base(el).classList.contains('badge--has-suffix')).to.be.false;
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
it('116. should add has-prefix and has-suffix classes when slots are filled', async () => {
|
|
798
|
+
const el = await fixture<NileBadge>(html`
|
|
799
|
+
<nile-badge><span slot="prefix">a</span>Label<span slot="suffix">b</span></nile-badge>
|
|
800
|
+
`);
|
|
801
|
+
expect(base(el).classList.contains('badge--has-prefix')).to.be.true;
|
|
802
|
+
expect(base(el).classList.contains('badge--has-suffix')).to.be.true;
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
it('117. should update classes when slot content is added later', async () => {
|
|
806
|
+
const el = await fixture<NileBadge>(html`<nile-badge>Label</nile-badge>`);
|
|
807
|
+
const icon = document.createElement('span');
|
|
808
|
+
icon.slot = 'prefix';
|
|
809
|
+
el.prepend(icon);
|
|
810
|
+
await elementUpdated(el);
|
|
811
|
+
await el.updateComplete;
|
|
812
|
+
expect(base(el).classList.contains('badge--has-prefix')).to.be.true;
|
|
813
|
+
});
|
|
814
|
+
|
|
815
|
+
it('118. should take no space when prefix and suffix are empty', async () => {
|
|
816
|
+
const el = await fixture<NileBadge>(html`<nile-badge>Label</nile-badge>`);
|
|
817
|
+
expect(slotOf(el, 'prefix').getBoundingClientRect().width).to.equal(0);
|
|
818
|
+
expect(slotOf(el, 'suffix').getBoundingClientRect().width).to.equal(0);
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
it('119. should space filled slots from the content with the spacing token', () => {
|
|
822
|
+
const css = styles.cssText;
|
|
823
|
+
const rule = (selector: string) => css.slice(css.indexOf(`${selector} {`)).split('}')[0];
|
|
824
|
+
const token = 'var(--nile-spacing-xs, var(--ng-spacing-xs))';
|
|
825
|
+
expect(rule('.badge--has-prefix .badge__prefix')).to.contain(`margin-inline-end: ${token}`);
|
|
826
|
+
expect(rule('.badge--has-suffix .badge__suffix')).to.contain(`margin-inline-start: ${token}`);
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
it('120. should keep slot content out of the aria-label', async () => {
|
|
830
|
+
const el = await fixture<NileBadge>(html`
|
|
831
|
+
<nile-badge><span slot="prefix">icon</span>Active<span slot="suffix">12</span></nile-badge>
|
|
832
|
+
`);
|
|
833
|
+
expect(el.getAttribute('aria-label')).to.equal('Active');
|
|
834
|
+
});
|
|
835
|
+
it('121. should ignore comment nodes in the aria-label', async () => {
|
|
836
|
+
const el = document.createElement('nile-badge') as NileBadge;
|
|
837
|
+
el.append(document.createComment('?lit$123$'), 'Active', document.createComment('ng-container'));
|
|
838
|
+
document.body.append(el);
|
|
839
|
+
await el.updateComplete;
|
|
840
|
+
expect(el.getAttribute('aria-label')).to.equal('Active');
|
|
841
|
+
el.remove();
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
it('122. should keep the existing label for badges without slots', async () => {
|
|
845
|
+
const el = await fixture<NileBadge>(html`<nile-badge>New <b>beta</b></nile-badge>`);
|
|
846
|
+
expect(el.getAttribute('aria-label')).to.equal('New beta');
|
|
847
|
+
});
|
|
848
|
+
});
|
|
747
849
|
});
|
|
@@ -15,6 +15,7 @@ import { styles } from './nile-badge.css';
|
|
|
15
15
|
import '../nile-icon-button/nile-icon-button';
|
|
16
16
|
import { classMap } from 'lit/directives/class-map.js';
|
|
17
17
|
import { customElement, property } from 'lit/decorators.js';
|
|
18
|
+
import { HasSlotController } from '../internal/slot';
|
|
18
19
|
import NileElement, { setupA11yMetadata } from '../internal/nile-element';
|
|
19
20
|
import type { CSSResultGroup } from 'lit';
|
|
20
21
|
import { A11yProperty } from '../internal/accessibility/a11y.property.enum';
|
|
@@ -35,27 +36,42 @@ import { A11yCustomValue } from '../internal/accessibility/a11y.custom-value.enu
|
|
|
35
36
|
* @dependency nile-icon-button
|
|
36
37
|
*
|
|
37
38
|
* @slot - The badge's content.
|
|
38
|
-
*
|
|
39
|
-
* @
|
|
39
|
+
* @slot prefix - Content placed before the badge's content, such as an icon, dot or avatar.
|
|
40
|
+
* @slot suffix - Content placed after the badge's content, such as an icon, count or button.
|
|
40
41
|
*
|
|
41
42
|
* @csspart base - The component's base wrapper.
|
|
43
|
+
* @csspart prefix - The container that wraps the prefix slot.
|
|
42
44
|
* @csspart content - The badge's content.
|
|
43
|
-
* @csspart
|
|
44
|
-
* @csspart remove-button__base - The remove button's exported `base` part.
|
|
45
|
+
* @csspart suffix - The container that wraps the suffix slot.
|
|
45
46
|
*/
|
|
46
47
|
|
|
47
48
|
@customElement('nile-badge')
|
|
48
49
|
export class NileBadge extends NileElement {
|
|
49
50
|
static styles: CSSResultGroup = styles;
|
|
50
51
|
|
|
52
|
+
private readonly hasSlotController = new HasSlotController(this, 'prefix', 'suffix');
|
|
53
|
+
|
|
51
54
|
connectedCallback(): void {
|
|
52
55
|
super.connectedCallback();
|
|
53
56
|
setupA11yMetadata(this, {
|
|
54
57
|
[Role.Role]: A11yRole.Text,
|
|
55
|
-
[A11yProperty.AriaLabel]: this.
|
|
58
|
+
[A11yProperty.AriaLabel]: this.getLabelText() || A11yCustomValue.Badge,
|
|
56
59
|
});
|
|
57
60
|
}
|
|
58
61
|
|
|
62
|
+
/** Text of the default slot only, so prefix and suffix content stays out of the label. */
|
|
63
|
+
private getLabelText(): string {
|
|
64
|
+
return [...this.childNodes]
|
|
65
|
+
.filter(
|
|
66
|
+
node =>
|
|
67
|
+
node.nodeType === Node.TEXT_NODE ||
|
|
68
|
+
(node.nodeType === Node.ELEMENT_NODE && !(node as Element).hasAttribute('slot'))
|
|
69
|
+
)
|
|
70
|
+
.map(node => node.textContent ?? '')
|
|
71
|
+
.join('')
|
|
72
|
+
.trim();
|
|
73
|
+
}
|
|
74
|
+
|
|
59
75
|
/** The badge's theme variant. */
|
|
60
76
|
@property({ reflect: true }) variant:
|
|
61
77
|
| 'primary'
|
|
@@ -88,6 +104,9 @@ export class NileBadge extends NileElement {
|
|
|
88
104
|
@property({ reflect: true }) size: 'sm' | 'md' | 'lg' = 'md';
|
|
89
105
|
|
|
90
106
|
render() {
|
|
107
|
+
const hasPrefix = this.hasSlotController.test('prefix');
|
|
108
|
+
const hasSuffix = this.hasSlotController.test('suffix');
|
|
109
|
+
|
|
91
110
|
return html`
|
|
92
111
|
<span
|
|
93
112
|
part="base"
|
|
@@ -117,9 +136,13 @@ export class NileBadge extends NileElement {
|
|
|
117
136
|
'badge--sm': this.size === 'sm',
|
|
118
137
|
'badge--md': this.size === 'md',
|
|
119
138
|
'badge--lg': this.size === 'lg',
|
|
139
|
+
'badge--has-prefix': hasPrefix,
|
|
140
|
+
'badge--has-suffix': hasSuffix,
|
|
120
141
|
})}
|
|
121
142
|
>
|
|
143
|
+
<slot name="prefix" part="prefix" class="badge__prefix"></slot>
|
|
122
144
|
<slot part="content" class="badge__content"></slot>
|
|
145
|
+
<slot name="suffix" part="suffix" class="badge__suffix"></slot>
|
|
123
146
|
</span>
|
|
124
147
|
`;
|
|
125
148
|
}
|
|
@@ -104,4 +104,61 @@ describe('NileBreadcrumb', () => {
|
|
|
104
104
|
it('98. slot is default (no name)', async () => { const el = await fixture<NileBreadcrumb>(html`<nile-breadcrumb><nile-breadcrumb-item>A</nile-breadcrumb-item></nile-breadcrumb>`); const slot = el.shadowRoot!.querySelector('slot'); expect(slot!.hasAttribute('name')).to.be.false; });
|
|
105
105
|
it('99. no nile-divider', async () => { const el = await fixture<NileBreadcrumb>(html`<nile-breadcrumb><nile-breadcrumb-item>A</nile-breadcrumb-item></nile-breadcrumb>`); expect(el.shadowRoot!.querySelector('nile-divider')).to.be.null; });
|
|
106
106
|
it('100. full integration', async () => { const el = await fixture<NileBreadcrumb>(html`<nile-breadcrumb class="b" id="b1" role="navigation" aria-label="Breadcrumb"><nile-breadcrumb-item>Home</nile-breadcrumb-item><nile-breadcrumb-item>Settings</nile-breadcrumb-item><nile-breadcrumb-item>Profile</nile-breadcrumb-item></nile-breadcrumb>`); expect(el.id).to.equal('b1'); expect(el.getAttribute('role')).to.equal('navigation'); expect(el.querySelectorAll('nile-breadcrumb-item').length).to.equal(3); expect(el.textContent).to.contain('Home'); expect(el.textContent).to.contain('Profile'); });
|
|
107
|
+
|
|
108
|
+
describe('variant', () => {
|
|
109
|
+
const tpl = (variant?: string) => variant
|
|
110
|
+
? html`<nile-breadcrumb variant=${variant}><nile-breadcrumb-item>A</nile-breadcrumb-item><nile-breadcrumb-item>B</nile-breadcrumb-item></nile-breadcrumb>`
|
|
111
|
+
: html`<nile-breadcrumb><nile-breadcrumb-item>A</nile-breadcrumb-item><nile-breadcrumb-item>B</nile-breadcrumb-item></nile-breadcrumb>`;
|
|
112
|
+
const items = (el: NileBreadcrumb) => [...el.querySelectorAll('nile-breadcrumb-item')];
|
|
113
|
+
|
|
114
|
+
it('defaults to "default" and reflects', async () => {
|
|
115
|
+
const el = await fixture<NileBreadcrumb>(tpl());
|
|
116
|
+
expect(el.variant).to.equal('default');
|
|
117
|
+
expect(el.getAttribute('variant')).to.equal('default');
|
|
118
|
+
items(el).forEach(i => expect(i.variant).to.equal('default'));
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('propagates "outlined" to every item', async () => {
|
|
122
|
+
const el = await fixture<NileBreadcrumb>(tpl('outlined'));
|
|
123
|
+
await Promise.all(items(el).map(i => i.updateComplete));
|
|
124
|
+
items(el).forEach(i => {
|
|
125
|
+
expect(i.getAttribute('variant')).to.equal('outlined');
|
|
126
|
+
expect(i.shadowRoot!.querySelector('[part="item"]')!.classList.contains('nile-breadcrumb-item--outlined')).to.be.true;
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('keeps the existing text-colour classes when outlined', async () => {
|
|
131
|
+
const el = await fixture<NileBreadcrumb>(tpl('outlined'));
|
|
132
|
+
const [a, b] = items(el);
|
|
133
|
+
await a.updateComplete; await b.updateComplete;
|
|
134
|
+
expect(a.shadowRoot!.querySelector('[part="item"]')!.classList.contains('nile-breadcrumb-item__slot-text')).to.be.true;
|
|
135
|
+
expect(b.shadowRoot!.querySelector('[part="item"]')!.classList.contains('nile-breadcrumb-item__last-slot-text')).to.be.true;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('updates items when variant changes at runtime', async () => {
|
|
139
|
+
const el = await fixture<NileBreadcrumb>(tpl());
|
|
140
|
+
el.variant = 'outlined';
|
|
141
|
+
await el.updateComplete;
|
|
142
|
+
items(el).forEach(i => expect(i.variant).to.equal('outlined'));
|
|
143
|
+
el.variant = 'default';
|
|
144
|
+
await el.updateComplete;
|
|
145
|
+
items(el).forEach(i => expect(i.variant).to.equal('default'));
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('applies the variant to items added later', async () => {
|
|
149
|
+
const el = await fixture<NileBreadcrumb>(tpl('outlined'));
|
|
150
|
+
const added = document.createElement('nile-breadcrumb-item');
|
|
151
|
+
added.textContent = 'C';
|
|
152
|
+
el.appendChild(added);
|
|
153
|
+
await new Promise(r => setTimeout(r));
|
|
154
|
+
expect(added.variant).to.equal('outlined');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('no chip class in the default variant', async () => {
|
|
158
|
+
const el = await fixture<NileBreadcrumb>(tpl());
|
|
159
|
+
const [a] = items(el);
|
|
160
|
+
await a.updateComplete;
|
|
161
|
+
expect(a.shadowRoot!.querySelector('.nile-breadcrumb-item--outlined')).to.be.null;
|
|
162
|
+
});
|
|
163
|
+
});
|
|
107
164
|
});
|
|
@@ -31,6 +31,12 @@ export class NileBreadcrumb extends NileElement {
|
|
|
31
31
|
return [styles];
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Visual style of the items. `outlined` renders each item inside an outlined chip;
|
|
36
|
+
* text colours are unchanged. Propagated to every slotted `nile-breadcrumb-item`.
|
|
37
|
+
*/
|
|
38
|
+
@property({ type: String, reflect: true }) variant: 'default' | 'outlined' = 'default';
|
|
39
|
+
|
|
34
40
|
/* #endregion */
|
|
35
41
|
|
|
36
42
|
/* #region Methods */
|
|
@@ -46,7 +52,20 @@ export class NileBreadcrumb extends NileElement {
|
|
|
46
52
|
});
|
|
47
53
|
}
|
|
48
54
|
|
|
55
|
+
protected updated(changedProperties: Map<string, unknown>) {
|
|
56
|
+
if (changedProperties.has('variant')) {
|
|
57
|
+
this.syncItemVariant();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private syncItemVariant() {
|
|
62
|
+
this.querySelectorAll('nile-breadcrumb-item').forEach(item => {
|
|
63
|
+
item.variant = this.variant;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
49
67
|
private changeLastItem() {
|
|
68
|
+
this.syncItemVariant();
|
|
50
69
|
const items: any = [...this.querySelectorAll('nile-breadcrumb-item')];
|
|
51
70
|
const itemslength = items.length;
|
|
52
71
|
for (let i = 0; i < itemslength - 1; i++) {
|
|
@@ -46,6 +46,18 @@ export const styles = css`
|
|
|
46
46
|
.nile-breadcrumb-item__last-slot-text {
|
|
47
47
|
color: var(--nile-breadcrumb-color, var(--ng-colors-text-brand-secondary-700));
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
.nile-breadcrumb-item--outlined {
|
|
51
|
+
padding: var(--nile-spacing-xs, var(--ng-spacing-xs)) var(--nile-spacing-md, var(--ng-spacing-md));
|
|
52
|
+
border: 1px solid var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
53
|
+
border-radius: var(--nile-radius-sm, var(--ng-radius-md));
|
|
54
|
+
background-color: var(--nile-colors-white-base, var(--ng-colors-bg-primary));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.nile-breadcrumb-item--outlined.nile-breadcrumb-item__slot-text:hover,
|
|
58
|
+
.nile-breadcrumb-item--outlined.nile-breadcrumb-item__last-slot-text {
|
|
59
|
+
background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-secondary));
|
|
60
|
+
}
|
|
49
61
|
`;
|
|
50
62
|
|
|
51
63
|
export default [styles];
|
|
@@ -44,6 +44,12 @@ export class NileBreadcrumbItem extends NileElement {
|
|
|
44
44
|
|
|
45
45
|
@property({ type: String }) separator = 'var(--nile-icon-arrow-right, var(--ng-icon-chevron-right))';
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Visual style of the item. `outlined` wraps the text in an outlined chip.
|
|
49
|
+
* Set automatically from the parent `nile-breadcrumb`'s `variant`.
|
|
50
|
+
*/
|
|
51
|
+
@property({ type: String, reflect: true }) variant: 'default' | 'outlined' = 'default';
|
|
52
|
+
|
|
47
53
|
private handleClick() {
|
|
48
54
|
if (this.isLast) {
|
|
49
55
|
return;
|
|
@@ -57,6 +63,7 @@ export class NileBreadcrumbItem extends NileElement {
|
|
|
57
63
|
class=${classMap({
|
|
58
64
|
'nile-breadcrumb-item__slot-text': !this.isLast,
|
|
59
65
|
'nile-breadcrumb-item__last-slot-text': this.isLast,
|
|
66
|
+
'nile-breadcrumb-item--outlined': this.variant === 'outlined',
|
|
60
67
|
})}
|
|
61
68
|
@click=${this.handleClick}
|
|
62
69
|
>
|