@exakt/ui 0.0.9 → 0.0.11

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 CHANGED
@@ -1,12 +1,3 @@
1
- <!--
2
- Get your module up and running quickly.
3
-
4
- Find and replace all on all files (CMD+SHIFT+F):
5
- - Name: exakt
6
- - Package name: @exakt/ui
7
- - Description: My new Nuxt module
8
- -->
9
-
10
1
  # exakt
11
2
 
12
3
  [![npm version][npm-version-src]][npm-version-href]
@@ -55,6 +46,12 @@ That's it! You can now use exakt in your Nuxt app ✨
55
46
 
56
47
  ## Development
57
48
 
49
+ ### Important note
50
+
51
+ Because mkdist (and subsequently nuxt-module-builder) don't yet support *not* compiling SASS files, you'll need to use ``yarn link`` to substitute mkdist with the force-scss-off branch of https://github.com/wd-4000/mkdist
52
+
53
+ ### The usual
54
+
58
55
  ```bash
59
56
  # Install dependencies
60
57
  npm install
package/dist/module.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "exakt-ui",
3
3
  "configKey": "exakt",
4
- "version": "0.0.9"
4
+ "version": "0.0.11"
5
5
  }
@@ -168,13 +168,19 @@ const hoverColor = computed(() => {
168
168
  border: none;
169
169
  text-decoration: none;
170
170
  cursor: pointer;
171
- position: relative;
172
171
  flex-shrink: 1;
173
-
172
+ position: relative;
174
173
  transition: background 0.4s, color 0.3s, opacity 0.4s;
175
174
 
176
175
  font-family: var(--e-font-family);
176
+ box-sizing: border-box;
177
177
 
178
+
179
+ border: transparent solid 0.1rem;
180
+ &:focus-visible {
181
+ transition: border-width 0.2s;
182
+ border: var(--e-color-dark) solid 0.1rem;
183
+ }
178
184
  &.loading {
179
185
  pointer-events: none;
180
186
 
@@ -196,6 +202,7 @@ const hoverColor = computed(() => {
196
202
 
197
203
  &:hover {
198
204
  background: rgba(98, 98, 98, 0.15);
205
+ border: transparent solid 0.1rem;
199
206
  }
200
207
 
201
208
  &:active {
@@ -14,8 +14,8 @@
14
14
  <script setup lang="ts">
15
15
  withDefaults(
16
16
  defineProps<{
17
- noBtnPadding: boolean;
18
- forceFullWidth: boolean;
17
+ noBtnPadding?: boolean;
18
+ forceFullWidth?: boolean;
19
19
 
20
20
  }>(),
21
21
  {
@@ -1,16 +1,17 @@
1
1
  <template>
2
- <div class="flex-stretch">
2
+ <div class="flex-stretch t-dropdown">
3
3
  <!-- class="flex-stretch fullwidth" -->
4
4
  <div
5
5
  ref="activator"
6
- @click="onClick"
6
+ @click="onActivatorClick"
7
7
  >
8
8
  <slot />
9
9
  </div>
10
- <e-focus-sheet v-model="state.active" />
10
+ <e-focus-sheet v-model="visibleComputed" />
11
11
  <e-tr-scale>
12
12
  <div
13
- v-if="state.active"
13
+ v-if="visibleComputed"
14
+ ref="list"
14
15
  class="list rounded"
15
16
  >
16
17
  <component
@@ -25,8 +26,12 @@
25
26
  class="item fullwidth"
26
27
  :color="item.color"
27
28
  :solid="false"
28
- :background="item.background || 'transparent'"
29
- :class="{ active: currentItem === i }"
29
+ :background="item.background || 'transparent'"
30
+ :class="{
31
+ 'rounded-top': i === 0,
32
+ 'rounded-bottom': i === items.length - 1,
33
+ active: currentItem === i,
34
+ }"
30
35
  @click="select(i)"
31
36
  >
32
37
  <e-icon
@@ -43,11 +48,58 @@
43
48
  </div>
44
49
  </template>
45
50
  <script setup lang="ts">
46
- import { computed, ref, reactive } from "#imports";
51
+ import { computed, ref, reactive, watch/*, nextTick*/ } from "#imports";
47
52
  import _ from "lodash";
48
53
 
54
+ interface DropdownItem {
55
+ name: string;
56
+ icon?: string;
57
+ href?: string;
58
+ callback?: () => void;
59
+ color?: string;
60
+ background?: string;
61
+ }
62
+
63
+ const props = withDefaults(
64
+ defineProps<{
65
+ modelValue?: number;
66
+ width: string | number | "100%";
67
+ center?: boolean;
68
+ items: DropdownItem[];
69
+ visible?: boolean | null;
70
+ paddingY?: string;
71
+ }>(),
72
+ { center: false, visible: null, paddingY: "", modelValue: undefined }
73
+ );
74
+
75
+ const activator = ref<HTMLDivElement>();
76
+ const list = ref<HTMLDivElement>();
77
+
78
+ const state = reactive({
79
+ visibleInternal: false,
80
+ x: 0,
81
+ y: 0,
82
+ width: 0,
83
+ });
49
84
 
50
- function parseWidth(input: string | number) {
85
+ // Visibility computed variable. We use the state unless we have a variable from the parent.
86
+ const visibleComputed = computed<boolean>({
87
+ get: () => {
88
+ if (props.visible != null) {
89
+ return props.visible;
90
+ }
91
+ return state.visibleInternal;
92
+ },
93
+ set: (value) => {
94
+ if (props.visible != null) {
95
+ emit("update:visible", value);
96
+ } else {
97
+ state.visibleInternal = value;
98
+ }
99
+ },
100
+ });
101
+
102
+ function computeWidth(input: string | number) {
51
103
  const div = document.createElement("div");
52
104
  document.body.appendChild(div);
53
105
  div.style.width = String(input);
@@ -58,88 +110,75 @@ function parseWidth(input: string | number) {
58
110
  return parseInt(c, 10);
59
111
  }
60
112
 
61
- const updatePosition = () => {
62
- if (!state.active) {
113
+ const updatePosition = async () => {
114
+ if (
115
+ !visibleComputed.value ||
116
+ !activator.value ||
117
+ !activator.value.firstElementChild
118
+ ) {
63
119
  window.removeEventListener("resize", debouncedUpdatePosition);
64
120
  return;
65
121
  }
66
- const rect = activator.value.getBoundingClientRect();
122
+ const activatorRect = activator.value.getBoundingClientRect();
67
123
 
68
- const dropdownWidth = parseWidth(props.width);
124
+ if (props.width === "100%") {
125
+ state.width = activatorRect.width;
126
+ } else {
127
+ state.width = computeWidth(props.width);
128
+ }
69
129
 
70
- state.y = rect.top + rect.height / 2;
130
+ state.y = activatorRect.height;
131
+ state.x = 0;
71
132
 
72
- const expectedDropdownRight = window.innerWidth - rect.left - dropdownWidth;
133
+ /* await nextTick();
134
+ if (!list.value) return;
73
135
 
74
- if (expectedDropdownRight - 50 >= 0) {
75
- // All is well.
76
- state.x = rect.left + rect.width / 2;
77
- } else {
78
- // We're going to overflow, gah!
79
- console.log("Overflow");
80
- state.x = rect.left + rect.width / 2 + expectedDropdownRight - 47;
81
- }
136
+ const listRect = list.value.getBoundingClientRect();
137
+ if (window.innerHeight < listRect.bottom) {
138
+ // The list is too low.
139
+ // We can just render the list on top of the button.
140
+ state.y = 0 - listRect.height;
141
+ } */
82
142
  };
83
143
 
84
144
  const debouncedUpdatePosition = _.debounce(updatePosition, 200);
85
145
 
86
- const onClick = (/*{ pageX, pageY }:MouseEvent*/) => {
87
- state.active = !state.active;
88
-
89
- if (state.active) {
146
+ watch(visibleComputed, (value) => {
147
+ if (value) {
90
148
  updatePosition();
91
149
  window.addEventListener("resize", debouncedUpdatePosition);
92
150
  } else {
93
151
  window.removeEventListener("resize", debouncedUpdatePosition);
94
152
  }
95
- };
96
-
97
- interface DropdownItem {
98
- name: string;
99
- icon?: string;
100
- href?: string;
101
- callback?: () => void;
102
- color?: string;
103
- background?: string;
104
- }
105
-
106
- const props = defineProps<{
107
- modelValue?: number;
108
- width: string | number;
109
- items: DropdownItem[];
110
- }>();
111
-
112
- const emit = defineEmits(["update:modelValue"]);
113
-
114
- const activator = ref();
115
-
116
- const state = reactive({
117
- active: false,
118
- x: 0,
119
- y: 0,
120
153
  });
121
154
 
155
+ const emit = defineEmits(["update:modelValue", "update:visible"]);
156
+
122
157
  const currentItem = computed({
123
158
  get: () => props.modelValue,
124
159
  set: (value) => emit("update:modelValue", value),
125
160
  });
126
161
 
127
-
128
-
129
162
  const select = (i: number) => {
130
- state.active = false;
163
+ visibleComputed.value = false;
131
164
  currentItem.value = i;
132
165
  };
166
+
167
+ const onActivatorClick = () => {
168
+ visibleComputed.value = !visibleComputed.value;
169
+ };
133
170
  </script>
134
171
  <style scoped lang="scss">
172
+ .t-dropdown {
173
+ position: relative;
174
+ }
135
175
  .list {
136
- position: fixed;
176
+ position: absolute;
137
177
  left: v-bind('state.x + "px"');
138
178
  top: v-bind('state.y + "px"');
139
- width: v-bind(width);
179
+ width: v-bind('state.width+"px"');
140
180
  display: flex;
141
181
 
142
-
143
182
  background-color: var(--e-color-elev-2);
144
183
  color: var(--e-color-dark);
145
184
  z-index: 4;
@@ -148,24 +187,34 @@ const select = (i: number) => {
148
187
  flex-direction: column;
149
188
  overflow: clip;
150
189
  justify-items: stretch;
190
+ margin-top: v-bind("props.paddingY");
151
191
 
152
192
  .item {
153
193
  // color: var(--e-color-dark);
154
194
  font-size: 1rem;
155
195
  padding: 0.7rem;
156
196
  text-transform: capitalize;
197
+ position: relative;
198
+
199
+ &:hover {
200
+ background-color: rgba(var(--e-color-dark-rgb), 0.2);
201
+ }
202
+ &:focus {
203
+ }
157
204
 
158
205
  &.active {
159
206
  background-color: rgba(var(--e-color-primary-rgb), 0.2);
160
207
 
208
+ &:hover {
209
+ background-color: rgba(var(--e-color-primary-rgb), 0.4);
210
+ }
161
211
  }
162
212
  }
163
213
  }
164
214
 
165
-
166
-
167
215
  @media screen and (max-width: $e-md-screen-breakpoint) {
168
216
  .list {
217
+ position: fixed;
169
218
  top: unset;
170
219
  bottom: 0px;
171
220
  left: 0px;
@@ -12,8 +12,8 @@
12
12
  withDefaults(
13
13
  defineProps<{
14
14
  icon: string;
15
- color: string;
16
- size: number | string;
15
+ color?: string;
16
+ size?: number | string;
17
17
  }>(),
18
18
  {
19
19
  icon: "",
@@ -23,7 +23,7 @@
23
23
  );
24
24
 
25
25
  </script>
26
- <style scoped>
26
+ <style scoped lang="css">
27
27
  svg {
28
28
  fill: currentColor;
29
29
  }
@@ -51,8 +51,8 @@ import {
51
51
  } from "vue";
52
52
 
53
53
  const props = defineProps<{
54
- width?: number;
55
- height?: number;
54
+ width: number;
55
+ height: number;
56
56
  aspectRatio?: number;
57
57
  blur?: string;
58
58
  src?: string;
@@ -65,7 +65,7 @@ const slots = useSlots();
65
65
  const wrapper = ref();
66
66
  const canvas = ref();
67
67
 
68
- const state = reactive({
68
+ const state = reactive<{loaded: boolean|undefined, renderBlur:boolean, blurHeight:number, blurWidth:number, resizeListenerActive:boolean, intersected:boolean}>({
69
69
  loaded: undefined,
70
70
  renderBlur: true,
71
71
  blurHeight: 32,
@@ -86,12 +86,15 @@ const slotContentPresent = computed(() => {
86
86
  return Boolean(slots.default);
87
87
  });
88
88
  const backgroundImage = computed(() => {
89
+ if(!props.src) {
90
+ return undefined;
91
+ }
89
92
  return "url(".concat(props.src, ")");
90
93
  });
91
94
 
92
95
  watch(
93
96
  () => props.blur,
94
- (newBlur: string) => {
97
+ (newBlur: string|undefined) => {
95
98
  if (!state.loaded) {
96
99
  initialize(newBlur);
97
100
  }
@@ -134,11 +137,15 @@ const getAspectRatio = () => {
134
137
  return undefined;
135
138
  };
136
139
 
137
- const dimensionFix = (value) => {
140
+ const dimensionFix = (value: string|number) => {
138
141
  if (!value) {
139
142
  return undefined;
140
143
  }
141
144
 
145
+ if(typeof value === "number") {
146
+ value = value.toString();
147
+ }
148
+
142
149
  if (/^\d+$/.test(value)) {
143
150
  return value + "px";
144
151
  }
@@ -147,7 +154,7 @@ const dimensionFix = (value) => {
147
154
 
148
155
 
149
156
 
150
- const onIntersect = (intersecting) => {
157
+ const onIntersect = (intersecting: boolean) => {
151
158
  if (intersecting && !state.intersected) {
152
159
  initialize();
153
160
  state.intersected = true;
@@ -0,0 +1,43 @@
1
+ <template>
2
+ <e-dropdown
3
+ v-model="dropdownActive"
4
+ :items="items"
5
+ width="100%"
6
+ :center="false"
7
+ :visible="dropdownVisible"
8
+ padding-y="0.25rem"
9
+ @update:visible="dropdownVisible = $event"
10
+ >
11
+ <e-input-text
12
+ v-model="searchField"
13
+ label="Input"
14
+ solid
15
+ />
16
+ </e-dropdown>
17
+ </template>
18
+ <script setup lang="ts">
19
+ import { ref, watch } from "#imports";
20
+ const items = [{ name: "test" }, { name: "test2" }, { name: "test3" }];
21
+ const dropdownActive = ref<undefined | number>(undefined);
22
+ const dropdownVisible = ref<boolean>(false);
23
+
24
+ const searchField = ref("");
25
+
26
+ watch(searchField, (value) => {
27
+ if (value.length > 0) {
28
+ //dropdownActive.value = 0;
29
+ dropdownVisible.value = true;
30
+ } else {
31
+ dropdownActive.value = undefined;
32
+ dropdownVisible.value = false;
33
+ }
34
+ });
35
+
36
+ watch(dropdownActive, (value) => {
37
+ if (value == undefined) {
38
+ searchField.value = "";
39
+ } else {
40
+ searchField.value = items[value].name;
41
+ }
42
+ });
43
+ </script>
@@ -1,47 +1,47 @@
1
1
  <template>
2
- <div class="pos-wrap">
3
- <div
4
- class="wrapper fullwidth"
5
- :style="inputState.overtakeStyle"
6
- :class="{ rounded: solid, solid }"
7
- @click="focus"
2
+ <!-- <div class="pos-wrap">-->
3
+ <div
4
+ class="wrapper fullwidth"
5
+ :style="inputState.overtakeStyle"
6
+ :class="{ rounded: solid, solid }"
7
+ @click="focus"
8
+ >
9
+ <e-icon
10
+ v-if="icon"
11
+ :icon="icon"
12
+ size="21"
13
+ />
14
+ <textarea
15
+ v-if="type === 'textarea'"
16
+ ref="input"
17
+ v-model="currentText"
18
+ class="input"
19
+ :placeholder="label"
20
+ autocomplete="off"
21
+ auto-grow
22
+ rows="5"
23
+ @focus="inputState.focused = true"
24
+ @blur="inputState.focused = false"
25
+ />
26
+ <input
27
+ v-else
28
+ ref="input"
29
+ v-model="currentText"
30
+ :disabled="disabled"
31
+ :type="type"
32
+ :autocomplete="autocomplete"
33
+ :spellcheck="spellcheck"
34
+ class="input"
35
+ :required="required"
36
+ :placeholder="label"
37
+ @click.stop=""
38
+ @focus="inputState.focused = true"
39
+ @blur="inputState.focused = false"
40
+ @transitionend="transitionEnd"
8
41
  >
9
- <e-icon
10
- v-if="icon"
11
- :icon="icon"
12
- size="21"
13
- />
14
- <textarea
15
- v-if="type === 'textarea'"
16
- ref="input"
17
- v-model="currentText"
18
- class="input"
19
- :placeholder="label"
20
- autocomplete="off"
21
- auto-grow
22
- rows="5"
23
- @focus="inputState.focused = true"
24
- @blur="inputState.focused = false"
25
- />
26
- <input
27
- v-else
28
- ref="input"
29
- v-model="currentText"
30
- :disabled="disabled"
31
- :type="type"
32
- :autocomplete="autocomplete"
33
- :spellcheck="spellcheck"
34
- class="input"
35
- :required="required"
36
- :placeholder="label"
37
- @click.stop=""
38
- @focus="inputState.focused = true"
39
- @blur="inputState.focused = false"
40
- @transitionend="transitionEnd"
41
- >
42
- <slot />
43
- </div>
42
+ <slot />
44
43
  </div>
44
+ <!-- </div>-->
45
45
  </template>
46
46
  <script setup lang="ts">
47
47
  import { ref, watch, reactive, computed } from "#imports";
@@ -111,7 +111,8 @@ watch(
111
111
  );
112
112
 
113
113
  const getInputStyle = (prop: string) => {
114
- const c = getComputedStyle(input.value)[prop] as any;
114
+ if(input.value === undefined) return;
115
+ const c = getComputedStyle(input.value).getPropertyValue(prop);
115
116
  return c;
116
117
  };
117
118
 
@@ -2,54 +2,53 @@
2
2
  <div />
3
3
  </template>
4
4
  <script setup lang="ts">
5
- const { $exakt } = useNuxtApp()
5
+ import { useNuxtApp, computed } from "#imports";
6
+
7
+ const { $exakt } = useNuxtApp();
6
8
  const props = withDefaults(
7
- defineProps<{
8
- color: string
9
- }>(),
10
- { color: 'primary' }
9
+ defineProps<{
10
+ color: string;
11
+ }>(),
12
+ { color: "primary" }
11
13
  );
12
- const parsedColor = computed(() => $exakt.parseColor(props.color, 'rgb'));
13
-
14
+ const parsedColor = computed(() => $exakt.parseColor(props.color, "rgb"));
14
15
  </script>
15
16
  <style scoped lang="scss">
16
17
  div {
17
- display: block;
18
- width: 100%;
19
- height: 100%;
20
- --pc: v-bind(parsedColor);
21
- background-image: linear-gradient(90deg,
22
- rgba(var(--pc), 0) 0%,
23
- rgba(var(--pc), 0.5) 50%,
24
- rgba(var(--pc), 0) 50.1%,
25
- rgba(var(--pc), 0) 100%,
26
-
27
- );
28
-
29
-
30
- background-size: 200% 100%;
31
-
32
- animation: pos 3.5s linear infinite;
18
+ display: block;
19
+ width: 100%;
20
+ height: 100%;
21
+ --pc: v-bind(parsedColor);
22
+ background-image: linear-gradient(
23
+ 90deg,
24
+ rgba(var(--pc), 0) 0%,
25
+ rgba(var(--pc), 0.5) 50%,
26
+ rgba(var(--pc), 0) 50.1%,
27
+ rgba(var(--pc), 0) 100%
28
+ );
29
+
30
+ background-size: 200% 100%;
31
+
32
+ animation: pos 3.5s linear infinite;
33
33
  }
34
34
 
35
35
  @keyframes pos {
36
- 0%,10% {
37
- background-position: 100% 0%;
38
- opacity: 1;
39
- }
40
- 40% {
41
- opacity: 1;
42
- }
43
-
44
- 70% {
45
- opacity: 0;
46
- }
47
-
48
- 100% {
49
- background-position: -100% 0%;
50
- opacity: 0;
51
- }
52
-
53
-
36
+ 0%,
37
+ 10% {
38
+ background-position: 100% 0%;
39
+ opacity: 1;
40
+ }
41
+ 40% {
42
+ opacity: 1;
43
+ }
44
+
45
+ 70% {
46
+ opacity: 0;
47
+ }
48
+
49
+ 100% {
50
+ background-position: -100% 0%;
51
+ opacity: 0;
52
+ }
54
53
  }
55
- </style>
54
+ </style>
@@ -10,8 +10,19 @@ $root-blue-rgb: red($root-blue), green($root-blue), blue($root-blue);
10
10
  .rounded {
11
11
  border-radius: var(--e-rounded-border-radius);
12
12
  }
13
+ .rounded-top {
14
+ border-top-left-radius: var(--e-rounded-border-radius);
15
+ border-top-right-radius: var(--e-rounded-border-radius);
16
+ }
13
17
 
18
+ .rounded-bottom {
19
+ border-bottom-left-radius: var(--e-rounded-border-radius);
20
+ border-bottom-right-radius: var(--e-rounded-border-radius);
21
+ }
14
22
 
23
+ body {
24
+ margin: 0px;
25
+ }
15
26
 
16
27
  $color-map: (
17
28
  "red": $root-red,
@@ -157,11 +157,11 @@ body {
157
157
  }
158
158
 
159
159
  @supports ((-webkit-backdrop-filter: none) or (backdrop-filter: none)) {
160
- .e-blur {
161
- backdrop-filter: blur(12px);
162
- background-color: rgba(255, 255, 255, 0.7);
163
- }
160
+ .e-blur {
161
+ backdrop-filter: blur(12px);
162
+ background-color: rgba(255, 255, 255, 0.7);
164
163
  }
164
+ }
165
165
 
166
166
  .e-disabled {
167
167
  opacity: 0.7;
@@ -1,6 +1,5 @@
1
1
  import { defineNuxtPlugin } from "#app";
2
2
  export default defineNuxtPlugin(() => {
3
- console.log("Plugin injected by exakt-ui!");
4
3
  return {
5
4
  provide: {
6
5
  exakt: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exakt/ui",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "A UI library for Nuxt.js",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,7 +22,7 @@
22
22
  "dev:build": "nuxi build playground",
23
23
  "dev:prepare": "nuxt-module-build --stub && nuxi prepare playground",
24
24
  "release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
25
- "lint": "eslint .",
25
+ "lint": "eslint . --fix",
26
26
  "test": "vitest run",
27
27
  "test:watch": "vitest watch"
28
28
  },
@@ -39,8 +39,10 @@
39
39
  "@nuxt/schema": "^3.2.3",
40
40
  "@nuxt/test-utils": "^3.2.3",
41
41
  "@types/lodash": "^4.14.191",
42
+ "@types/node": "^20.2.4",
42
43
  "changelogen": "^0.5.1",
43
44
  "eslint": "^8.35.0",
45
+ "mkdist": "^1.2.0",
44
46
  "nuxt": "^3.4.3",
45
47
  "vitest": "^0.29.2"
46
48
  },
@@ -62,5 +64,9 @@
62
64
  "bugs": {
63
65
  "url": "https://github.com/wd-4000/exakt/issues"
64
66
  },
65
- "homepage": "https://github.com/wd-4000/exakt#readme"
66
- }
67
+ "resolutions": {
68
+ "mkdist": "npm:@wd4000/mkdist-no-scss@1.2.0"
69
+ },
70
+ "homepage": "https://github.com/wd-4000/exakt#readme",
71
+ "packageManager": "yarn@3.5.1"
72
+ }