@propelinc/citrus-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.browserslistrc +3 -0
  2. package/.eslintrc.js +4 -0
  3. package/.stylelintrc.js +8 -0
  4. package/README.md +29 -0
  5. package/babel.config.js +3 -0
  6. package/dist/citrus-ui.common.js +27312 -0
  7. package/dist/citrus-ui.common.js.map +1 -0
  8. package/dist/citrus-ui.css +1 -0
  9. package/dist/citrus-ui.umd.js +27322 -0
  10. package/dist/citrus-ui.umd.js.map +1 -0
  11. package/dist/citrus-ui.umd.min.js +32 -0
  12. package/dist/citrus-ui.umd.min.js.map +1 -0
  13. package/dist/demo.html +10 -0
  14. package/jest.config.js +4 -0
  15. package/package.json +80 -0
  16. package/plopfile.js +67 -0
  17. package/postcss.config.js +5 -0
  18. package/src/assets/fonts/ObjectSans-Black.woff2 +0 -0
  19. package/src/assets/fonts/ObjectSans-BlackSlanted.woff2 +0 -0
  20. package/src/assets/fonts/ObjectSans-Bold.woff2 +0 -0
  21. package/src/assets/fonts/ObjectSans-BoldSlanted.woff2 +0 -0
  22. package/src/assets/fonts/ObjectSans-Heavy.woff2 +0 -0
  23. package/src/assets/fonts/ObjectSans-HeavySlanted.woff2 +0 -0
  24. package/src/assets/fonts/ObjectSans-Regular.woff2 +0 -0
  25. package/src/assets/fonts/ObjectSans-Slanted.woff2 +0 -0
  26. package/src/assets/fonts/ObjectSans-Thin.woff2 +0 -0
  27. package/src/assets/fonts/ObjectSans-ThinSlanted.woff2 +0 -0
  28. package/src/colors/colors.json +37 -0
  29. package/src/colors/theme.ts +29 -0
  30. package/src/components/CAlert.vue +85 -0
  31. package/src/components/CBanner.vue +46 -0
  32. package/src/components/CButton.vue +95 -0
  33. package/src/components/CCard.vue +50 -0
  34. package/src/components/CIconButton.vue +61 -0
  35. package/src/components/CListItem.vue +80 -0
  36. package/src/components/CModalLoading.vue +54 -0
  37. package/src/components/CSkeletonLoaderCircle.vue +24 -0
  38. package/src/components/CSkeletonLoaderText.vue +38 -0
  39. package/src/components/CTextField.vue +101 -0
  40. package/src/index.d.ts +29 -0
  41. package/src/index.ts +24 -0
  42. package/src/shims-vue.d.ts +4 -0
  43. package/src/shims-vuetify.d.ts +4 -0
  44. package/src/styles/object-sans.less +23 -0
  45. package/src/styles/typography.less +36 -0
  46. package/src/styles/variables.less +117 -0
  47. package/tsconfig.json +42 -0
  48. package/vue.config.js +17 -0
@@ -0,0 +1,54 @@
1
+ <template>
2
+ <v-dialog
3
+ data-test="modal-loading"
4
+ width="160"
5
+ persistent
6
+ no-click-animation
7
+ :value="value"
8
+ @input="(value) => $emit('input', value)"
9
+ >
10
+ <v-card class="modal-loading__content">
11
+ <font-awesome-icon :icon="faSync" class="fa-spin modal-loading__icon" />
12
+
13
+ <div data-test="modal-loading-message" class="modal-loading__content__message">
14
+ <slot>
15
+ {{ message }}
16
+ </slot>
17
+ </div>
18
+ </v-card>
19
+ </v-dialog>
20
+ </template>
21
+
22
+ <script lang="ts">
23
+ import { faSync } from '@fortawesome/pro-light-svg-icons';
24
+ import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
25
+ import { Component, Vue, Prop } from 'vue-property-decorator';
26
+
27
+ @Component({ name: 'CModalLoading', components: { FontAwesomeIcon } })
28
+ export default class CModalLoading extends Vue {
29
+ faSync = faSync;
30
+
31
+ @Prop({ type: Boolean, default: false }) value!: boolean;
32
+ @Prop({ type: String }) message?: string;
33
+ }
34
+ </script>
35
+
36
+ <style lang="less" scoped>
37
+ @import '~@/styles/variables.less';
38
+
39
+ .modal-loading__icon {
40
+ color: @color-blue-accent;
41
+ font-size: @font-size-2x-large;
42
+ }
43
+
44
+ .modal-loading__content {
45
+ border-radius: @border-radius !important; // Override Vuetify styles
46
+ padding: 28px 16px 20px;
47
+ text-align: center;
48
+ }
49
+
50
+ .modal-loading__content__message {
51
+ font-weight: @font-weight-bold;
52
+ margin: 12px 0 0;
53
+ }
54
+ </style>
@@ -0,0 +1,24 @@
1
+ <template>
2
+ <div data-test="skeleton-loader-circle" class="skeleton-loader-circle" />
3
+ </template>
4
+
5
+ <script lang="ts">
6
+ import { Component, Vue } from 'vue-property-decorator';
7
+
8
+ @Component({ name: 'CSkeletonLoaderCircle' })
9
+ export default class CSkeletonLoaderCircle extends Vue {}
10
+ </script>
11
+
12
+ <style lang="less" scoped>
13
+ @import '~@/styles/variables.less';
14
+
15
+ @skeleton-loader-circle-size: 36px;
16
+
17
+ .skeleton-loader-circle {
18
+ .skeleton-loader();
19
+
20
+ border-radius: @skeleton-loader-circle-size / 2;
21
+ height: @skeleton-loader-circle-size;
22
+ width: @skeleton-loader-circle-size;
23
+ }
24
+ </style>
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <div data-test="skeleton-loader-text" class="skeleton-loader-text">
3
+ <div v-for="x in rows" :key="x" class="skeleton-loader-text__line" />
4
+ </div>
5
+ </template>
6
+
7
+ <script lang="ts">
8
+ import { Component, Vue, Prop } from 'vue-property-decorator';
9
+
10
+ @Component({ name: 'CSkeletonLoaderText' })
11
+ export default class CSkeletonLoaderText extends Vue {
12
+ @Prop({ type: Number, default: 2 }) rows!: number;
13
+ }
14
+ </script>
15
+
16
+ <style lang="less" scoped>
17
+ @import '~@/styles/variables.less';
18
+
19
+ .skeleton-loader-text {
20
+ width: 100%;
21
+ }
22
+
23
+ .skeleton-loader-text__line {
24
+ .skeleton-loader();
25
+
26
+ border-radius: 2px;
27
+ height: @font-size-medium;
28
+ width: 100%;
29
+
30
+ & + & {
31
+ margin-top: 4px;
32
+ }
33
+
34
+ &:last-child {
35
+ width: calc(100% - 32px);
36
+ }
37
+ }
38
+ </style>
@@ -0,0 +1,101 @@
1
+ <template>
2
+ <fieldset :disabled="disabled">
3
+ <label
4
+ v-if="label"
5
+ :for="id"
6
+ data-test="text-field-label"
7
+ class="text-field__label"
8
+ :class="{ 'text-field__label--disabled': disabled }"
9
+ >
10
+ {{ label }}
11
+ </label>
12
+
13
+ <v-text-field
14
+ :id="id"
15
+ v-bind="$attrs"
16
+ data-test="text-field"
17
+ class="text-field__field"
18
+ :class="{ 'text-field__field--disabled': disabled }"
19
+ outlined
20
+ single-line
21
+ :placeholder="placeholder"
22
+ :disabled="disabled"
23
+ :type="type"
24
+ :value="value"
25
+ :rules="rules"
26
+ validate-on-blur
27
+ hide-details="auto"
28
+ @input="(value) => $emit('input', value)"
29
+ />
30
+ </fieldset>
31
+ </template>
32
+
33
+ <script lang="ts">
34
+ import { Component, Vue, Prop } from 'vue-property-decorator';
35
+
36
+ @Component({ name: 'CTextField' })
37
+ export default class CTextField extends Vue {
38
+ @Prop(String) label?: string;
39
+ @Prop(String) placeholder?: string;
40
+ @Prop({ type: String, required: true }) id!: string;
41
+ @Prop({ type: String, default: 'text' }) type!: string;
42
+ @Prop({ type: Boolean, default: false }) disabled!: boolean;
43
+ @Prop({ type: String, default: '' }) value!: boolean;
44
+ @Prop(Array) rules?: ((value: string) => string | boolean)[];
45
+ }
46
+ </script>
47
+
48
+ <style lang="less" scoped>
49
+ @import '~@/styles/variables.less';
50
+
51
+ @color-disabled-text: @color-navy-tint-2;
52
+
53
+ .text-field__label {
54
+ font-weight: @font-weight-bold;
55
+ margin: 0 0 4px 2px;
56
+ }
57
+
58
+ .text-field__label--disabled {
59
+ color: @color-disabled-text;
60
+ }
61
+
62
+ .text-field__field {
63
+ & /deep/ legend {
64
+ display: none;
65
+ }
66
+
67
+ &.v-input--is-focused /deep/ fieldset,
68
+ &.v-input--has-state /deep/ fieldset {
69
+ border-color: currentColor;
70
+ border-width: 1px;
71
+ }
72
+
73
+ & /deep/ .v-input__slot {
74
+ min-height: 48px;
75
+ padding: 0 16px !important; // Override Vuetify.
76
+ }
77
+
78
+ & /deep/ input {
79
+ .body();
80
+
81
+ line-height: 20px;
82
+ }
83
+ }
84
+
85
+ /deep/ fieldset {
86
+ background: @color-white;
87
+ border-color: @color-neutral-shade;
88
+ border-radius: @border-radius;
89
+ top: 0;
90
+ }
91
+
92
+ .text-field__field--disabled {
93
+ & /deep/ fieldset {
94
+ background: @color-neutral-shade;
95
+ }
96
+
97
+ & /deep/ input {
98
+ color: @color-disabled-text;
99
+ }
100
+ }
101
+ </style>
package/src/index.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { VueConstructor } from 'vue';
2
+
3
+ import _Theme from '@/colors/theme';
4
+
5
+ export declare const Theme: typeof _Theme;
6
+
7
+ const CAlert: VueConstructor;
8
+ const CBanner: VueConstructor;
9
+ const CButton: VueConstructor;
10
+ const CCard: VueConstructor;
11
+ const CIconButton: VueConstructor;
12
+ const CListItem: VueConstructor;
13
+ const CModalLoading: VueConstructor;
14
+ const CSkeletonLoaderCircle: VueConstructor;
15
+ const CSkeletonLoaderText: VueConstructor;
16
+ const CTextField: VueConstructor;
17
+
18
+ export {
19
+ CAlert,
20
+ CBanner,
21
+ CButton,
22
+ CCard,
23
+ CIconButton,
24
+ CListItem,
25
+ CModalLoading,
26
+ CSkeletonLoaderCircle,
27
+ CSkeletonLoaderText,
28
+ CTextField,
29
+ };
package/src/index.ts ADDED
@@ -0,0 +1,24 @@
1
+ import _Theme from '@/colors/theme';
2
+ import _CAlert from '@/components/CAlert.vue';
3
+ import _CBanner from '@/components/CBanner.vue';
4
+ import _CButton from '@/components/CButton.vue';
5
+ import _CCard from '@/components/CCard.vue';
6
+ import _CIconButton from '@/components/CIconButton.vue';
7
+ import _CListItem from '@/components/CListItem.vue';
8
+ import _CModalLoading from '@/components/CModalLoading.vue';
9
+ import _CSkeletonLoaderCircle from '@/components/CSkeletonLoaderCircle.vue';
10
+ import _CSkeletonLoaderText from '@/components/CSkeletonLoaderText.vue';
11
+ import _CTextField from '@/components/CTextField.vue';
12
+
13
+ export const Theme = _Theme;
14
+
15
+ export const CAlert = _CAlert;
16
+ export const CBanner = _CBanner;
17
+ export const CButton = _CButton;
18
+ export const CCard = _CCard;
19
+ export const CIconButton = _CIconButton;
20
+ export const CListItem = _CListItem;
21
+ export const CModalLoading = _CModalLoading;
22
+ export const CSkeletonLoaderCircle = _CSkeletonLoaderCircle;
23
+ export const CSkeletonLoaderText = _CSkeletonLoaderText;
24
+ export const CTextField = _CTextField;
@@ -0,0 +1,4 @@
1
+ declare module '*.vue' {
2
+ import Vue from 'vue';
3
+ export default Vue;
4
+ }
@@ -0,0 +1,4 @@
1
+ declare module 'vuetify/lib/framework' {
2
+ import Vuetify from 'vuetify';
3
+ export default Vuetify;
4
+ }
@@ -0,0 +1,23 @@
1
+ @import "~@/styles/variables.less";
2
+
3
+ .ObjectSans(@font-weight, @file-name-normal, @file-name-slanted) {
4
+ @font-face {
5
+ font-family: @font-family-object-sans;
6
+ font-style: normal;
7
+ font-weight: @font-weight;
8
+ src: url('~@/assets/fonts/@{file-name-normal}.woff2') format('woff2'),
9
+ }
10
+
11
+ @font-face {
12
+ font-family: @font-family-object-sans;
13
+ font-style: italic;
14
+ font-weight: @font-weight;
15
+ src: url('~@/assets/fonts/@{file-name-slanted}.woff2') format('woff2'),
16
+ }
17
+ }
18
+
19
+ .ObjectSans(@font-weight-thin, 'ObjectSans-Thin', 'ObjectSans-ThinSlanted');
20
+ .ObjectSans(@font-weight-normal, 'ObjectSans-Regular', 'ObjectSans-Slanted');
21
+ .ObjectSans(@font-weight-bold, 'ObjectSans-Bold', 'ObjectSans-BoldSlanted');
22
+ .ObjectSans(@font-weight-heavy, 'ObjectSans-Heavy', 'ObjectSans-HeavySlanted');
23
+ .ObjectSans(@font-weight-black, 'ObjectSans-Black', 'ObjectSans-BlackSlanted');
@@ -0,0 +1,36 @@
1
+ @import "~@/styles/variables.less";
2
+
3
+ .body();
4
+
5
+ .balance {
6
+ .balance();
7
+ }
8
+
9
+ .large-headline {
10
+ .large-headline();
11
+ }
12
+
13
+ .headline {
14
+ .headline();
15
+ }
16
+
17
+ .subheadline {
18
+ .subheadline();
19
+ }
20
+
21
+ .title {
22
+ .title();
23
+ }
24
+
25
+ p,
26
+ .body {
27
+ .body();
28
+ }
29
+
30
+ .caption {
31
+ .caption();
32
+ }
33
+
34
+ .overline {
35
+ .overline();
36
+ }
@@ -0,0 +1,117 @@
1
+ // BORDERS
2
+ @color-border: @color-neutral-shade;
3
+ @border-width: 1px;
4
+ @border: @border-width solid @color-border;
5
+
6
+ @border-radius: 8px;
7
+
8
+ // TYPOGRAPHY
9
+ @font-family-object-sans: ObjectSans;
10
+
11
+ @font-weight-thin: 100;
12
+ @font-weight-light: 300; // Currently unused, but holding its place in case we add it.
13
+ @font-weight-normal: 400;
14
+ @font-weight-medium: 500; // Currently unused, but holding its place in case we add it.
15
+ @font-weight-bold: 700;
16
+ @font-weight-heavy: 800;
17
+ @font-weight-black: 900;
18
+
19
+ @font-size-3x-large: 44px;
20
+ @font-size-2x-large: 32px;
21
+ @font-size-x-large: 23px;
22
+ @font-size-large: 18px;
23
+ @font-size-medium: 14px;
24
+ @font-size-small: 12px;
25
+
26
+ @line-height-balance: 100%;
27
+ @line-height-large-headline: 85%;
28
+ @line-height-headline: 130%;
29
+ @line-height-subheadline: 130%;
30
+ @line-height-body: 150%;
31
+ @line-height-caption: 150%;
32
+ @line-height-overline: 100%;
33
+
34
+ .balance() {
35
+ font-family: @font-family-object-sans !important;
36
+ font-size: @font-size-2x-large !important;
37
+ font-weight: @font-weight-thin;
38
+ line-height: @line-height-balance;
39
+ }
40
+
41
+ .large-headline() {
42
+ font-family: @font-family-object-sans !important;
43
+ font-size: @font-size-2x-large !important;
44
+ font-weight: @font-weight-black;
45
+ line-height: @line-height-large-headline;
46
+ text-transform: uppercase;
47
+ }
48
+
49
+ .headline() {
50
+ font-family: @font-family-object-sans !important;
51
+ font-size: @font-size-x-large !important;
52
+ font-weight: @font-weight-heavy;
53
+ line-height: @line-height-headline;
54
+ }
55
+
56
+ .subheadline() {
57
+ font-family: @font-family-object-sans !important;
58
+ font-size: @font-size-large !important;
59
+ font-weight: @font-weight-heavy;
60
+ line-height: @line-height-subheadline;
61
+ }
62
+
63
+ .title() {
64
+ .body;
65
+
66
+ font-weight: @font-weight-heavy;
67
+ }
68
+
69
+ .body() {
70
+ font-family: @font-family-object-sans !important;
71
+ font-size: @font-size-medium !important;
72
+ font-weight: @font-weight-normal;
73
+ line-height: @line-height-body;
74
+ }
75
+
76
+ .caption() {
77
+ font-family: @font-family-object-sans !important;
78
+ font-size: @font-size-small !important;
79
+ font-weight: @font-weight-normal;
80
+ letter-spacing: 0 !important;
81
+ line-height: @line-height-caption;
82
+ }
83
+
84
+ .overline() {
85
+ font-family: @font-family-object-sans !important;
86
+ font-size: @font-size-small !important ;
87
+ font-weight: @font-weight-heavy;
88
+ letter-spacing: 0 !important;
89
+ line-height: @line-height-overline;
90
+ text-transform: uppercase;
91
+ }
92
+
93
+ // SKELETON LOADER
94
+ @skeleton-loader-animation-duration: 3s;
95
+ @skeleton-loader-animation: skeleton-loader-animation @skeleton-loader-animation-duration infinite;
96
+
97
+ @keyframes skeleton-loader-animation {
98
+ 0% {
99
+ background-position: 150%;
100
+ }
101
+ 100% {
102
+ background-position: -50%;
103
+ }
104
+ }
105
+
106
+ .skeleton-loader(@color-base: @color-navy-tint-3, @color-highlight: @color-navy-tint-4) {
107
+ animation: @skeleton-loader-animation;
108
+ background: linear-gradient(75deg, @color-base 30%, @color-highlight 50%, @color-base 70%);
109
+ background-size: 200% 150%;
110
+ }
111
+
112
+ .skeleton-loader-text(@color-font: @color-navy, @color-highlight: @color-navy-tint-2) {
113
+ .skeleton-loader(@color-font, @color-highlight);
114
+
115
+ background-clip: text;
116
+ -webkit-text-fill-color: transparent;
117
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "esnext",
4
+ "module": "esnext",
5
+ "strict": true,
6
+ "jsx": "preserve",
7
+ "importHelpers": true,
8
+ "moduleResolution": "node",
9
+ "experimentalDecorators": true,
10
+ "skipLibCheck": true,
11
+ "esModuleInterop": true,
12
+ "allowSyntheticDefaultImports": true,
13
+ "resolveJsonModule": true,
14
+ "sourceMap": true,
15
+ "baseUrl": ".",
16
+ "types": [
17
+ "webpack-env",
18
+ "jest"
19
+ ],
20
+ "paths": {
21
+ "@/*": [
22
+ "src/*"
23
+ ]
24
+ },
25
+ "lib": [
26
+ "esnext",
27
+ "dom",
28
+ "dom.iterable",
29
+ "scripthost"
30
+ ]
31
+ },
32
+ "include": [
33
+ "src/**/*.ts",
34
+ "src/**/*.tsx",
35
+ "src/**/*.vue",
36
+ "tests/**/*.ts",
37
+ "tests/**/*.tsx"
38
+ ],
39
+ "exclude": [
40
+ "node_modules"
41
+ ]
42
+ }
package/vue.config.js ADDED
@@ -0,0 +1,17 @@
1
+ const fs = require('fs');
2
+
3
+ const ProvideColors = JSON.parse(fs.readFileSync('./src/colors/colors.json'));
4
+
5
+ module.exports = {
6
+ css: {
7
+ loaderOptions: {
8
+ less: {
9
+ globalVars: ProvideColors,
10
+ },
11
+ },
12
+ },
13
+
14
+ lintOnSave: true,
15
+
16
+ transpileDependencies: ['vuetify'],
17
+ };