@thinkpixellab-public/px-vue 4.0.11 → 4.0.13

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.
@@ -0,0 +1,39 @@
1
+ <script>
2
+ import { h, createVNode } from 'vue';
3
+ import { parse } from '@vue/compiler-dom';
4
+
5
+ export default {
6
+ name: 'px-svg-render',
7
+ props: {
8
+ svg: { type: String, default: null },
9
+ },
10
+ data() {
11
+ return {
12
+ mounted: false,
13
+ };
14
+ },
15
+ mounted() {
16
+ this.mounted = true;
17
+ },
18
+ render() {
19
+ if (!this.svg || !this.mounted) {
20
+ return null;
21
+ }
22
+ // create a template element and set its inner html to the svg content
23
+ const template = document.createElement('template');
24
+ template.innerHTML = this.svg?.trim();
25
+
26
+ // extract the actual svg element
27
+ const svgElement = template.content.firstChild;
28
+
29
+ // convert the svg element to a vnode
30
+ return h(svgElement.tagName, {
31
+ innerHTML: svgElement.innerHTML,
32
+ ...Array.from(svgElement.attributes).reduce((acc, attr) => {
33
+ acc[attr.name] = attr.value;
34
+ return acc;
35
+ }, {}),
36
+ });
37
+ },
38
+ };
39
+ </script>
@@ -213,7 +213,7 @@ export default {
213
213
  * sorting and a direction (ascending/descending) and raises and event (@sort) when it
214
214
  * changes, but the actual sorting need to be handle externally by sorting the items).
215
215
  */
216
- sortEnabled: { type: Boolean, default: true },
216
+ sortEnabled: { type: Boolean, default: false },
217
217
 
218
218
  /**
219
219
  * A function that can be used to provide custom sorting. If not provided, a default
@@ -329,14 +329,16 @@ export default {
329
329
  },
330
330
  // watch: {},
331
331
  mounted() {
332
- this.sortable = Sortable.create(this.$refs.table, {
333
- draggable: `.${this.bem('row')}`,
334
- filter: `.${this.bem('row-expand')}, .${this.bem('row-header')}`,
335
- chosenClass: this.bem('row--chosen'),
336
- ghostClass: this.bem('row--ghost'),
337
- dragClass: this.bem('row--drag'),
338
- onEnd: this.onDragEnd,
339
- });
332
+ if (this.dragEnabled) {
333
+ this.sortable = Sortable.create(this.$refs.table, {
334
+ draggable: `.${this.bem('row')}`,
335
+ filter: `.${this.bem('row-expand')}, .${this.bem('row-header')}`,
336
+ chosenClass: this.bem('row--chosen'),
337
+ ghostClass: this.bem('row--ghost'),
338
+ dragClass: this.bem('row--drag'),
339
+ onEnd: this.onDragEnd,
340
+ });
341
+ }
340
342
  },
341
343
  beforeUnmount() {
342
344
  this.sortable.destroy();
@@ -469,21 +471,64 @@ export default {
469
471
  @use '../styles/px.scss' as *;
470
472
  @use '@thinkpixellab-public/px-styles/src/modules/controls' as *;
471
473
 
472
- .px-table {
473
- // load defaults
474
+ @at-root {
475
+ :root {
476
+ // background for the entire table
477
+ --px-table-bg: #{clr(page-bg)};
474
478
 
475
- // the outer container for the table (use to style an outer border, etc.)
479
+ // background for the entire table
480
+ --px-table-fg: #{clr(page-fg)};
476
481
 
477
- $table: flat-merge(
478
- get(
479
- 'controls.table.table',
480
- (
481
- border: 1px solid gray(5),
482
- border-radius: get('controls.border-radius'),
483
- )
484
- )
485
- );
482
+ // outer border for the entire table
483
+ --px-table-border: 1px solid #{gray(2, 0.5)};
484
+
485
+ // outer border radius for the entire table
486
+ --px-table-radius: 0.5em;
487
+
488
+ // inner border radius (may need to be less than outer in some cases)
489
+ --px-table-inner-radius: initial;
490
+
491
+ // background for the header row
492
+ --px-table-header-bg: #{gray(8)};
493
+
494
+ // background for the header row
495
+ --px-table-header-fg: unset;
496
+
497
+ // separator border below the header row
498
+ --px-table-header-border: 1px solid #{gray(2, 0.5)};
499
+
500
+ // background for all non-header rows
501
+ --px-table-row-bg: unset;
502
+
503
+ // background for all non-header rows
504
+ --px-table-row-fg: unset;
486
505
 
506
+ // background for odd non-header rows
507
+ --px-table-row-odd-bg: unset;
508
+
509
+ // background for odd non-header rows
510
+ --px-table-row-odd-fg: unset;
511
+
512
+ // separator border below each row
513
+ --px-table-row-border: 1px solid #{gray(2, 0.5)};
514
+
515
+ // cell padding
516
+ --px-table-cell-padding: 1em;
517
+
518
+ // header cell padding
519
+ --px-table-header-cell-padding: 1em;
520
+
521
+ // header cell hover (when clickable)
522
+ --px-table-header-cell-hover-bg: #{gray(5)};
523
+ --px-table-header-cell-hover-fg: unset;
524
+
525
+ // header cell selected (e.g. sorted)
526
+ --px-table-header-cell-selected-bg: #{accent(0)};
527
+ --px-table-header-cell-selected-fg: #{contrast-color(accent(0))};
528
+ }
529
+ }
530
+
531
+ .px-table {
487
532
  // row states that can be used when defining config for cell and header
488
533
 
489
534
  $cell-state-aliases: (
@@ -499,8 +544,6 @@ export default {
499
544
  'controls.table.cell',
500
545
  (
501
546
  padding: 0.5em,
502
- background-color: color(page-bg),
503
- border-bottom: 1px solid gray(5),
504
547
  last-row: (
505
548
  border-bottom: none,
506
549
  ),
@@ -508,46 +551,37 @@ export default {
508
551
  )
509
552
  );
510
553
 
511
- $header: flat-merge(
512
- get(
513
- 'controls.table.header',
514
- (
515
- background-color: gray(9),
516
- )
517
- )
518
- );
519
-
520
- // outer grid for the container (not the tabble itself)
521
- // position: relative;
522
- // display: grid;
523
- // grid-template-columns: 1fr;
524
- // grid-template-rows: 100%;
525
-
526
- @include css-map($table);
554
+ background: var(--px-table-bg);
555
+ color: var(--px-table-fg);
556
+ border: var(--px-table-border);
557
+ border-radius: var(--px-table-radius);
527
558
 
528
559
  &__table {
529
560
  position: relative;
530
561
  display: grid;
531
562
  height: 100%;
532
563
  max-height: 100%;
564
+ border-radius: inherit;
565
+ box-sizing: border-box;
533
566
  }
534
567
 
535
568
  &__row-header,
536
569
  &__row {
537
570
  position: relative;
538
- //display: contents;
539
571
  display: grid;
540
572
  grid-template-columns: subgrid;
541
- background-color: clr(page-bg);
542
-
543
- &:not(:last-child) {
544
- border-bottom: 1px solid gray(3);
545
- }
546
573
  }
547
574
 
548
575
  &__row-header {
549
- @include css-map($header, $aliases: $cell-state-aliases);
576
+ //@include css-map($header, $aliases: $cell-state-aliases);
550
577
  z-index: 1;
578
+ background: var(--px-table-header-bg);
579
+ color: var(--px-table-header-fg);
580
+ border-bottom: var(--px-table-header-border);
581
+
582
+ border-top-left-radius: var(--px-table-inner-radius, inherit);
583
+ border-top-right-radius: var(--px-table-inner-radius, inherit);
584
+
551
585
  &[role='button'] {
552
586
  cursor: pointer;
553
587
  }
@@ -557,8 +591,34 @@ export default {
557
591
  }
558
592
  }
559
593
 
594
+ &__row {
595
+ background: var(--px-table-row-bg);
596
+ color: var(--px-table-row-fg);
597
+
598
+ &:nth-child(odd) {
599
+ background: var(--px-table-row-odd-bg);
600
+ color: var(--px-table-row-odd-fg);
601
+ }
602
+
603
+ &:not(:last-child) {
604
+ border-bottom: var(--px-table-row-border);
605
+ }
606
+
607
+ &:last-child {
608
+ border-bottom-left-radius: var(--px-table-inner-radius, inherit);
609
+ border-bottom-right-radius: var(--px-table-inner-radius, inherit);
610
+ }
611
+ }
612
+
560
613
  &__cell-header {
561
614
  @include control-reset-hard();
615
+ &:first-child {
616
+ border-top-left-radius: var(--px-table-inner-radius, inherit);
617
+ }
618
+
619
+ &:last-child {
620
+ border-top-right-radius: var(--px-table-inner-radius, inherit);
621
+ }
562
622
  }
563
623
 
564
624
  &__cell-header,
@@ -569,21 +629,25 @@ export default {
569
629
  box-sizing: border-box;
570
630
  display: flex;
571
631
  align-items: center;
572
- padding: 0.5em;
632
+ padding: var(--px-table-cell-padding);
573
633
 
574
634
  // overflow
575
635
  overflow: hidden;
576
636
  white-space: nowrap;
577
637
  text-overflow: ellipsis;
638
+ line-height: 1.33;
578
639
 
579
640
  &--action {
580
641
  padding: 0.5em;
581
642
  }
582
643
  }
583
644
 
645
+ &__cell-header {
646
+ }
647
+
584
648
  &__cell-header-default,
585
649
  &__cell-default {
586
- display: inline-block;
650
+ display: block;
587
651
  max-width: 100%;
588
652
  width: 100%;
589
653
  overflow: hidden;
@@ -620,15 +684,25 @@ export default {
620
684
  }
621
685
 
622
686
  &__cell-header {
623
- padding-top: 0.75em;
624
- padding-bottom: 0.75em;
687
+ // padding-top: 0.75em;
688
+ // padding-bottom: 0.75em;
689
+
690
+ padding: var(--px-table-header-cell-padding);
625
691
 
626
692
  &--sortable {
627
693
  cursor: pointer;
628
694
  &:hover {
629
- background-color: gray(6);
695
+ background: var(--px-table-header-cell-hover-bg, inherit);
696
+ color: var(--px-table-header-cell-hover-fg, inherit);
630
697
  }
631
698
  }
699
+
700
+ &--sorted,
701
+ &--sorted:hover {
702
+ cursor: pointer;
703
+ background: var(--px-table-header-cell-selected-bg, inherit);
704
+ color: var(--px-table-header-cell-selected-fg, inherit);
705
+ }
632
706
  }
633
707
 
634
708
  &__expand-toggle {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkpixellab-public/px-vue",
3
- "version": "4.0.11",
3
+ "version": "4.0.13",
4
4
  "description": "General purpose Vue components and helpers that can be used across projects.",
5
5
  "author": "Pixel Lab",
6
6
  "license": "MIT",
@@ -29,6 +29,7 @@
29
29
  "dateformat": "^5.0.3",
30
30
  "debounce": "^1.2.1",
31
31
  "gsap": "^3.10.4",
32
+ "highlight.js": "^11.9.0",
32
33
  "mitt": "^3.0.1",
33
34
  "qrcode": "^1.5.1",
34
35
  "qrcode.vue": "^3.4.1",
@@ -36,6 +37,7 @@
36
37
  "storybook-dark-mode": "^4.0.1",
37
38
  "throttle-debounce": "^5.0.0",
38
39
  "tiny-date-picker": "^3.2.8",
40
+ "tinycolor2": "^1.6.0",
39
41
  "vue": "^3.4.21",
40
42
  "vue-inline-svg": "^3.1.0"
41
43
  },
@@ -0,0 +1,53 @@
1
+ // Reference:
2
+ // https://storybook.js.org/blog/storybook-7-docs/
3
+ // https://storybook.js.org/docs/7.5/writing-docs/autodocs
4
+
5
+ import PxCodeSample from '@/components/PxCodeSample.vue';
6
+ import extractArgTypes from './helpers/extractArgTypes';
7
+
8
+ export default {
9
+ component: PxCodeSample,
10
+ // decorators: [ ... ],
11
+ // parameters: { ... },
12
+
13
+ // https://storybook.js.org/docs/7.0/vue/essentials/controls#annotation
14
+ // https://storybook.js.org/docs/7.0/vue/api/argtypes#available-properties
15
+ argTypes: {
16
+ ...extractArgTypes(PxCodeSample),
17
+ // someProp: { type: 'select', options: ['one', 'two', 'three'] }
18
+ },
19
+ args: {
20
+ // label: 'Hello',
21
+ // onClick: () => {}),
22
+ },
23
+ };
24
+
25
+ const htmlSample = `
26
+ <div>
27
+ <h1>Hello World</h1>
28
+ <p>This is a paragraph</p>
29
+ </div>
30
+ `;
31
+
32
+ export const Basic = {
33
+ // name: 'Story Name',
34
+ render: (args, { argTypes }) => ({
35
+ components: { PxCodeSample },
36
+ setup() {
37
+ return { args };
38
+ },
39
+ data() {
40
+ return {
41
+ htmlSample,
42
+ };
43
+ },
44
+ template: `<PxCodeSample v-bind="args"
45
+ :code="htmlSample" :lang="'html'"
46
+ />`,
47
+ }),
48
+ };
49
+
50
+ // export const Advanced = {
51
+ // ...Basic,
52
+ // // args: { ... },
53
+ // };
@@ -0,0 +1,59 @@
1
+ import PxColorPalette from '@/components/PxColorPalette.vue';
2
+
3
+ import extractArgTypes from './helpers/extractArgTypes';
4
+
5
+ export default {
6
+ title: 'PxColorPalette',
7
+ component: PxColorPalette,
8
+ // decorators: [ ... ],
9
+ // parameters: { ... },
10
+
11
+ // https://storybook.js.org/docs/7.0/vue/essentials/controls#annotation
12
+ // https://storybook.js.org/docs/7.0/vue/api/argtypes#available-properties
13
+ argTypes: {
14
+ ...extractArgTypes(PxColorPalette),
15
+ // someProp: { type: 'select', options: ['one', 'two', 'three'] }
16
+ },
17
+ args: {
18
+ // label: 'Hello',
19
+ // onClick: () => {}),
20
+ color: 'black',
21
+ },
22
+ };
23
+
24
+ export const Basic = {
25
+ render: (args, { argTypes }) => ({
26
+ components: { PxColorPalette },
27
+ setup() {
28
+ return { args };
29
+ },
30
+ data() {
31
+ return {
32
+ myPalette: ['lightblue', 'yellowgreen', 'gold', 'orangered', 'tomato'],
33
+ myColor: 'yellowgreen',
34
+ };
35
+ },
36
+ template: `
37
+ <PxColorPalette v-model:color="myColor" :palette="myPalette" format="name" pickerMode="none"></PxColorPalette>
38
+ <br>
39
+ <br>
40
+ <PxColorPalette v-model:color="myColor" :palette="myPalette" format="name" pickerMode="picker"></PxColorPalette>
41
+ <br>
42
+ <br>
43
+ <PxColorPalette v-model:color="myColor" :palette="myPalette" format="name" pickerMode="eyedropper"></PxColorPalette>
44
+ <br>
45
+ <br>
46
+ <PxColorPalette v-model:color="myColor" :palette="myPalette" format="name" pickerMode="eyedropper-only"></PxColorPalette>
47
+ <br>
48
+ <br>
49
+
50
+ {{myColor}}<br>
51
+
52
+ `,
53
+ }),
54
+ };
55
+
56
+ // export const Advanced = {
57
+ // ...Basic,
58
+ // // args: { ... },
59
+ // };
@@ -0,0 +1,45 @@
1
+ import PxColorPanel from '@/components/PxColorPanel.vue';
2
+ import PxTextbox from '@/components/PxTextbox.vue';
3
+ import extractArgTypes from './helpers/extractArgTypes';
4
+
5
+ export default {
6
+ title: 'PxColorPanel',
7
+ component: PxColorPanel,
8
+ // decorators: [ ... ],
9
+ // parameters: { ... },
10
+
11
+ // https://storybook.js.org/docs/7.0/vue/essentials/controls#annotation
12
+ // https://storybook.js.org/docs/7.0/vue/api/argtypes#available-properties
13
+ argTypes: {
14
+ ...extractArgTypes(PxColorPanel),
15
+ // someProp: { type: 'select', options: ['one', 'two', 'three'] }
16
+ },
17
+ args: {
18
+ // label: 'Hello',
19
+ // onClick: () => {}),
20
+ color: 'black',
21
+ },
22
+ };
23
+
24
+ export const Basic = {
25
+ render: (args, { argTypes }) => ({
26
+ components: { PxColorPanel, PxTextbox },
27
+ setup() {
28
+ return { args };
29
+ },
30
+ data() {
31
+ return { myColor: 'purple' };
32
+ },
33
+ template: `
34
+ <PxColorPanel v-model:color="myColor" format="hex8" :alphaEnabled="true"></PxColorPanel>
35
+ <br>
36
+ {{myColor}}<br>
37
+ <PxTextbox v-model:value="myColor" variant="default">test</PxTextbox>
38
+ `,
39
+ }),
40
+ };
41
+
42
+ // export const Advanced = {
43
+ // ...Basic,
44
+ // // args: { ... },
45
+ // };
@@ -0,0 +1,44 @@
1
+ import PxColorPicker from '@/components/PxColorPicker.vue';
2
+ import extractArgTypes from './helpers/extractArgTypes';
3
+
4
+ export default {
5
+ title: 'PxColorPicker',
6
+ component: PxColorPicker,
7
+ // decorators: [ ... ],
8
+ // parameters: { ... },
9
+
10
+ // https://storybook.js.org/docs/7.0/vue/essentials/controls#annotation
11
+ // https://storybook.js.org/docs/7.0/vue/api/argtypes#available-properties
12
+ argTypes: {
13
+ ...extractArgTypes(PxColorPicker),
14
+ // someProp: { type: 'select', options: ['one', 'two', 'three'] }
15
+ },
16
+ args: {
17
+ // label: 'Hello',
18
+ // onClick: () => {}),
19
+ color: 'black',
20
+ },
21
+ };
22
+
23
+ export const Basic = {
24
+ render: (args, { argTypes }) => ({
25
+ components: { PxColorPicker },
26
+ setup() {
27
+ return { args };
28
+ },
29
+ data() {
30
+ return { myColor: 'purple' };
31
+ },
32
+ template: `
33
+ <PxColorPicker v-model:color="myColor" format="hex8" :alphaEnabled="true"></PxColorPanel>
34
+ <br>
35
+ {{myColor}}<br>
36
+
37
+ `,
38
+ }),
39
+ };
40
+
41
+ // export const Advanced = {
42
+ // ...Basic,
43
+ // // args: { ... },
44
+ // };
@@ -0,0 +1,44 @@
1
+ // Reference:
2
+ // https://storybook.js.org/blog/storybook-7-docs/
3
+ // https://storybook.js.org/docs/7.5/writing-docs/autodocs
4
+
5
+ import PxLabeledInput from '@/components/PxLabeledInput.vue';
6
+ import extractArgTypes from './helpers/extractArgTypes';
7
+
8
+ export default {
9
+ component: PxLabeledInput,
10
+ // decorators: [ ... ],
11
+ // parameters: { ... },
12
+
13
+ // https://storybook.js.org/docs/7.0/vue/essentials/controls#annotation
14
+ // https://storybook.js.org/docs/7.0/vue/api/argtypes#available-properties
15
+ argTypes: {
16
+ ...extractArgTypes(PxLabeledInput),
17
+ // someProp: { type: 'select', options: ['one', 'two', 'three'] }
18
+ },
19
+ args: {
20
+ label: 'My Input',
21
+ // onClick: () => {}),
22
+ },
23
+ };
24
+
25
+ export const Basic = {
26
+ // name: 'Story Name',
27
+ render: (args, { argTypes }) => ({
28
+ components: { PxLabeledInput },
29
+ setup() {
30
+ return { args };
31
+ },
32
+ template: `
33
+ <PxLabeledInput v-bind="args">
34
+ <template #default="{id}">
35
+ <input :id="id" type="text" />
36
+ </template>
37
+ </PxLabeledInput>`,
38
+ }),
39
+ };
40
+
41
+ // export const Advanced = {
42
+ // ...Basic,
43
+ // // args: { ... },
44
+ // };
@@ -0,0 +1,40 @@
1
+ import PxSvgRender from '@/components/PxSvgRender.vue';
2
+ import extractArgTypes from './helpers/extractArgTypes';
3
+ import { svgArrow } from '../utils/svgIcons';
4
+
5
+ import alphaSvg from './assets/alpha.svg';
6
+
7
+ export default {
8
+ component: PxSvgRender,
9
+ // decorators: [ ... ],
10
+ // parameters: { ... },
11
+
12
+ // https://storybook.js.org/docs/7.0/vue/essentials/controls#annotation
13
+ // https://storybook.js.org/docs/7.0/vue/api/argtypes#available-properties
14
+ argTypes: {
15
+ ...extractArgTypes(PxSvgRender),
16
+ // someProp: { type: 'select', options: ['one', 'two', 'three'] }
17
+ svg: { control: 'text' },
18
+ },
19
+ args: {
20
+ // label: 'Hello',
21
+ // onClick: () => {}),
22
+ },
23
+ };
24
+
25
+ export const Basic = {
26
+ // name: 'Story Name',
27
+ render: (args, { argTypes }) => ({
28
+ components: { PxSvgRender },
29
+ setup() {
30
+ return { args };
31
+ },
32
+ template: `<PxSvgRender v-bind="args" :svg="svgArrow()" />`,
33
+ methods: { svgArrow },
34
+ }),
35
+ };
36
+
37
+ export const Advanced = {
38
+ ...Basic,
39
+ // args: { size: '2em' },
40
+ };
@@ -0,0 +1,54 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import MockComponent from './MockComponent.vue';
3
+ import PxBaseColor from '@/bases/PxBaseColor.vue';
4
+
5
+ test('PxBaseColor', () => {
6
+ const wrapper = shallowMount(MockComponent, {
7
+ mixins: [PxBaseColor],
8
+ });
9
+ expect(wrapper.vm.getColor()).toEqual({
10
+ a: 1,
11
+ h: 0,
12
+ s: 1,
13
+ v: 1,
14
+ });
15
+ });
16
+
17
+ test('PxBaseColor with color initialized to blue and hex6 format', () => {
18
+ const wrapper = shallowMount(MockComponent, {
19
+ mixins: [PxBaseColor],
20
+ props: {
21
+ color: 'blue',
22
+ format: 'hex6',
23
+ },
24
+ });
25
+
26
+ expect(wrapper.vm.getColor()).toEqual('#0000ff');
27
+ });
28
+
29
+ test('PxBaseColor with color initialized to blue and hsva format', () => {
30
+ const wrapper = shallowMount(MockComponent, {
31
+ mixins: [PxBaseColor],
32
+ props: {
33
+ color: { a: 0.5, h: 0, s: 0.5, v: 0.5 },
34
+ format: 'hsva',
35
+ },
36
+ });
37
+ expect(wrapper.vm.getColor()).toEqual({
38
+ a: 0.5,
39
+ h: 0,
40
+ s: 0.5,
41
+ v: 0.5,
42
+ });
43
+ });
44
+
45
+ test('PxBaseColor test auto format', () => {
46
+ const wrapper = shallowMount(MockComponent, {
47
+ mixins: [PxBaseColor],
48
+ props: {
49
+ color: 'green',
50
+ format: 'auto',
51
+ },
52
+ });
53
+ expect(wrapper.vm.getColor()).toEqual('green');
54
+ });