wally-ui 1.12.1 → 1.13.1
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/dist/cli.js +8 -5
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/playground/showcase/src/app/app.routes.server.ts +4 -0
- package/playground/showcase/src/app/components/ai/ai-composer/ai-composer.html +164 -31
- package/playground/showcase/src/app/components/ai/ai-composer/ai-composer.ts +25 -3
- package/playground/showcase/src/app/components/ai/ai-prompt-input/ai-prompt-input.html +1 -1
- package/playground/showcase/src/app/components/badge/badge.css +0 -0
- package/playground/showcase/src/app/components/badge/badge.html +3 -0
- package/playground/showcase/src/app/components/badge/badge.ts +24 -0
- package/playground/showcase/src/app/components/button/button.html +1 -3
- package/playground/showcase/src/app/components/button/button.ts +4 -4
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-content/dropdown-menu-content.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-content/dropdown-menu-content.html +9 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-content/dropdown-menu-content.spec.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-content/dropdown-menu-content.ts +167 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-group/dropdown-menu-group.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-group/dropdown-menu-group.html +5 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-group/dropdown-menu-group.spec.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-group/dropdown-menu-group.ts +10 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-item/dropdown-menu-item.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-item/dropdown-menu-item.html +6 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-item/dropdown-menu-item.spec.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-item/dropdown-menu-item.ts +37 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-label/dropdown-menu-label.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-label/dropdown-menu-label.html +3 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-label/dropdown-menu-label.spec.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-label/dropdown-menu-label.ts +11 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-portal/dropdown-menu-portal.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-portal/dropdown-menu-portal.html +1 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-portal/dropdown-menu-portal.spec.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-portal/dropdown-menu-portal.ts +11 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-separator/dropdown-menu-separator.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-separator/dropdown-menu-separator.html +1 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-separator/dropdown-menu-separator.spec.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-separator/dropdown-menu-separator.ts +11 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub/dropdown-menu-sub.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub/dropdown-menu-sub.html +3 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub/dropdown-menu-sub.spec.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub/dropdown-menu-sub.ts +16 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub-content/dropdown-menu-sub-content.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub-content/dropdown-menu-sub-content.html +9 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub-content/dropdown-menu-sub-content.spec.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub-content/dropdown-menu-sub-content.ts +140 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub-trigger/dropdown-menu-sub-trigger.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub-trigger/dropdown-menu-sub-trigger.html +13 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub-trigger/dropdown-menu-sub-trigger.spec.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub-trigger/dropdown-menu-sub-trigger.ts +40 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub.service.spec.ts +16 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-sub.service.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-trigger/dropdown-menu-trigger.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-trigger/dropdown-menu-trigger.html +8 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-trigger/dropdown-menu-trigger.spec.ts +23 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-trigger/dropdown-menu-trigger.ts +55 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu.css +0 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu.html +3 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu.service.spec.ts +16 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu.service.ts +31 -0
- package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu.ts +69 -0
- package/playground/showcase/src/app/components/tooltip/tooltip.ts +195 -80
- package/playground/showcase/src/app/pages/documentation/components/components.html +110 -51
- package/playground/showcase/src/app/pages/documentation/components/components.routes.ts +4 -0
- package/playground/showcase/src/app/pages/documentation/components/dropdown-menu-docs/dropdown-menu-docs.css +1 -0
- package/playground/showcase/src/app/pages/documentation/components/dropdown-menu-docs/dropdown-menu-docs.examples.ts +404 -0
- package/playground/showcase/src/app/pages/documentation/components/dropdown-menu-docs/dropdown-menu-docs.html +612 -0
- package/playground/showcase/src/app/pages/documentation/components/dropdown-menu-docs/dropdown-menu-docs.ts +127 -0
- package/playground/showcase/src/app/pages/home/home.html +10 -6
package/dist/cli.js
CHANGED
|
@@ -64,11 +64,14 @@ program
|
|
|
64
64
|
}
|
|
65
65
|
const playgroundPath = path_1.default.join(__dirname, '..', 'playground', 'showcase', 'src', 'app', 'components', component);
|
|
66
66
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
await fs_extra_1.default.
|
|
67
|
+
if (!await fs_extra_1.default.pathExists(playgroundPath)) {
|
|
68
|
+
console.log(chalk_1.default.red(`Component '${component}' not found in playground`));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
await fs_extra_1.default.copy(playgroundPath, componentPath, {
|
|
72
|
+
overwrite: true,
|
|
73
|
+
errorOnExist: false
|
|
74
|
+
});
|
|
72
75
|
console.log(chalk_1.default.green('Template loaded successfully!'));
|
|
73
76
|
}
|
|
74
77
|
catch (error) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAoC;AACpC,wDAAgC;AAChC,wDAA0B;AAC1B,kDAA0B;AAC1B,gDAAwB;AAExB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,WAAW,CAAC;;;;;;;;;;CAU7B,CAAC,CAAC,CAAC;AAEJ,MAAM,OAAO,GAAY,IAAI,mBAAO,EAAE,CAAC;AAEvC,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAE,EAAE;IACzC,MAAM,EAAE,GAAG,kBAAQ,CAAC,eAAe,CAAC;QAChC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACzB,CAAC,CAAC;IAEH,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QACzB,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;YAC3B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC;QAC1F,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,OAAO;KACF,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,6BAA6B,CAAC;KAC1C,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB,OAAO;KACF,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,qBAAqB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;IACxB,gDAAgD;IAChD,IAAI,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,YAAY,CAAC,qBAAqB,SAAS,2CAA2C,CAAC,CAAC,CAAC;QAC3G,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,UAAU,CAAC,0CAA0C,CAAC,GAAG,eAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;QACpH,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC,CAAC;QAC9F,OAAO;IACX,CAAC;IAED,2BAA2B;IAC3B,IAAI,CAAC,kBAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,SAAS,CAAC,2DAA2D,CAAC,CAAC,CAAC;QAC1F,OAAO;IACX,CAAC;IAED,MAAM,aAAa,GAAG,+BAA+B,SAAS,EAAE,CAAC;IAEjE,IAAI,MAAM,kBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,YAAY,CAAC,cAAc,SAAS,uBAAuB,aAAa,EAAE,CAAC,CAAC,CAAC;QAC/F,MAAM,eAAe,GAAG,MAAM,eAAe,CACzC,eAAK,CAAC,UAAU,CAAC,+BAA+B,CAAC,GAAG,eAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAC5E,CAAC;QAEF,IAAI,CAAC,eAAe,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;YAChD,OAAO;QACX,CAAC;IACL,CAAC;IAED,MAAM,cAAc,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;IAEnH,IAAI,CAAC;QACD,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -29,6 +29,10 @@ export const serverRoutes: ServerRoute[] = [
|
|
|
29
29
|
path: 'documentation/components/tooltip',
|
|
30
30
|
renderMode: RenderMode.Prerender,
|
|
31
31
|
},
|
|
32
|
+
{
|
|
33
|
+
path: 'documentation/components/dropdown-menu',
|
|
34
|
+
renderMode: RenderMode.Prerender,
|
|
35
|
+
},
|
|
32
36
|
{
|
|
33
37
|
path: 'documentation/chat-sdk',
|
|
34
38
|
renderMode: RenderMode.Prerender,
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
<div class="w-full flex flex-col" role="region" aria-label="AI message composer">
|
|
2
2
|
<!-- Selected Text Context -->
|
|
3
3
|
<div class="p-0.5">
|
|
4
|
-
<div
|
|
5
|
-
id="selected-context"
|
|
4
|
+
<div id="selected-context"
|
|
6
5
|
class="w-full flex items-center gap-1 justify-between border bg-neutral-100 border-neutral-300 dark:bg-[#121212] dark:border-neutral-700 rounded-t-3xl rounded-b-lg p-3"
|
|
7
|
-
role="status"
|
|
8
|
-
aria-live="polite">
|
|
6
|
+
role="status" aria-live="polite">
|
|
9
7
|
<div class="w-full flex gap-4 items-center">
|
|
10
8
|
<svg viewBox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg"
|
|
11
|
-
class="size-5 text-[#0a0a0a] dark:text-white"
|
|
12
|
-
aria-hidden="true">
|
|
9
|
+
class="size-5 text-[#0a0a0a] dark:text-white" aria-hidden="true">
|
|
13
10
|
<path
|
|
14
11
|
d="M12.5293 6.5293C12.7566 6.30203 13.1081 6.27383 13.3662 6.44434L13.4707 6.5293L17.4707 10.5293C17.7304 10.789 17.7304 11.211 17.4707 11.4707L13.4707 15.4707C13.211 15.7304 12.789 15.7304 12.5293 15.4707C12.2696 15.211 12.2696 14.789 12.5293 14.5293L15.3936 11.665H6C3.97588 11.665 2.33496 10.0241 2.33496 8V4.5C2.33496 4.13273 2.63273 3.83496 3 3.83496C3.36727 3.83496 3.66504 4.13273 3.66504 4.5V8C3.66504 9.28958 4.71042 10.335 6 10.335H15.3936L12.5293 7.4707L12.4443 7.36621C12.2738 7.10808 12.302 6.75657 12.5293 6.5293Z">
|
|
15
12
|
</path>
|
|
@@ -21,10 +18,7 @@
|
|
|
21
18
|
</div>
|
|
22
19
|
|
|
23
20
|
<div>
|
|
24
|
-
<wally-button
|
|
25
|
-
[variant]="'ghost'"
|
|
26
|
-
[rounded]="true"
|
|
27
|
-
[ariaLabel]="'Clear selected context'">
|
|
21
|
+
<wally-button [variant]="'ghost'" [rounded]="true" [ariaLabel]="'Clear selected context'">
|
|
28
22
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
29
23
|
stroke="currentColor" class="size-5" aria-hidden="true">
|
|
30
24
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
|
|
@@ -40,30 +34,169 @@
|
|
|
40
34
|
|
|
41
35
|
<!-- Action Buttons -->
|
|
42
36
|
<div class="w-full flex justify-between px-2 pb-2" role="toolbar" aria-label="Composer actions">
|
|
43
|
-
<div class="
|
|
44
|
-
<
|
|
45
|
-
<wally-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
37
|
+
<div class="w-full flex items-center gap-1">
|
|
38
|
+
<div class="size-10">
|
|
39
|
+
<wally-dropdown-menu>
|
|
40
|
+
<wally-dropdown-menu-trigger>
|
|
41
|
+
<wally-tooltip [text]="'Add files and more'" position="bottom">
|
|
42
|
+
<wally-button [variant]="'ghost'" [rounded]="true"
|
|
43
|
+
[ariaLabel]="'Add attachment or insert content'">
|
|
44
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2"
|
|
45
|
+
stroke="currentColor" class="size-5" aria-hidden="true">
|
|
46
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
|
47
|
+
</svg>
|
|
48
|
+
</wally-button>
|
|
49
|
+
</wally-tooltip>
|
|
50
|
+
</wally-dropdown-menu-trigger>
|
|
51
|
+
|
|
52
|
+
<wally-dropdown-menu-content [position]="'top'">
|
|
53
|
+
<!-- Grupo 1: Configurações da conta -->
|
|
54
|
+
<wally-dropdown-menu-group [ariaLabel]="'Account settings'">
|
|
55
|
+
<wally-dropdown-menu-item (click)="onItemClick()">
|
|
56
|
+
<div class="flex items-center gap-3">
|
|
57
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
58
|
+
stroke-width="1.5" stroke="currentColor" class="size-6">
|
|
59
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
|
60
|
+
d="M12 18v-5.25m0 0a6.01 6.01 0 0 0 1.5-.189m-1.5.189a6.01 6.01 0 0 1-1.5-.189m3.75 7.478a12.06 12.06 0 0 1-4.5 0m3.75 2.383a14.406 14.406 0 0 1-3 0M14.25 18v-.192c0-.983.658-1.823 1.508-2.316a7.5 7.5 0 1 0-7.517 0c.85.493 1.509 1.333 1.509 2.316V18" />
|
|
61
|
+
</svg>
|
|
62
|
+
|
|
63
|
+
<span>
|
|
64
|
+
Think
|
|
65
|
+
</span>
|
|
66
|
+
</div>
|
|
67
|
+
</wally-dropdown-menu-item>
|
|
68
|
+
|
|
69
|
+
<wally-dropdown-menu-item (click)="onItemClick()">
|
|
70
|
+
<div class="flex items-center gap-3">
|
|
71
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
72
|
+
stroke-width="1.5" stroke="currentColor" class="size-6">
|
|
73
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
|
74
|
+
d="M9 8.25H7.5a2.25 2.25 0 0 0-2.25 2.25v9a2.25 2.25 0 0 0 2.25 2.25h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25H15m0-3-3-3m0 0-3 3m3-3V15" />
|
|
75
|
+
</svg>
|
|
76
|
+
|
|
77
|
+
<span>
|
|
78
|
+
Upload File
|
|
79
|
+
</span>
|
|
80
|
+
</div>
|
|
81
|
+
</wally-dropdown-menu-item>
|
|
82
|
+
|
|
83
|
+
<!-- Submenu -->
|
|
84
|
+
<wally-dropdown-menu-sub>
|
|
85
|
+
<wally-dropdown-menu-sub-trigger>
|
|
86
|
+
<div class="flex items-center gap-3">
|
|
87
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
88
|
+
stroke-width="1.5" stroke="currentColor" class="size-6">
|
|
89
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
|
90
|
+
d="M6.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM12.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0ZM18.75 12a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z" />
|
|
91
|
+
</svg>
|
|
92
|
+
|
|
93
|
+
<span>
|
|
94
|
+
More
|
|
95
|
+
</span>
|
|
96
|
+
</div>
|
|
97
|
+
</wally-dropdown-menu-sub-trigger>
|
|
98
|
+
|
|
99
|
+
<wally-dropdown-menu-sub-content>
|
|
100
|
+
<wally-dropdown-menu-item (click)="onItemClick()">
|
|
101
|
+
<div class="flex items-center gap-3">
|
|
102
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
103
|
+
stroke-width="1.5" stroke="currentColor" class="size-6">
|
|
104
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
|
105
|
+
d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" />
|
|
106
|
+
</svg>
|
|
107
|
+
|
|
108
|
+
<span>
|
|
109
|
+
Search the web
|
|
110
|
+
</span>
|
|
111
|
+
</div>
|
|
112
|
+
</wally-dropdown-menu-item>
|
|
113
|
+
<wally-dropdown-menu-item (click)="onItemClick()">
|
|
114
|
+
<div class="flex items-center gap-3">
|
|
115
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
116
|
+
stroke-width="1.5" stroke="currentColor" class="size-6">
|
|
117
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
|
118
|
+
d="M4.26 10.147a60.438 60.438 0 0 0-.491 6.347A48.62 48.62 0 0 1 12 20.904a48.62 48.62 0 0 1 8.232-4.41 60.46 60.46 0 0 0-.491-6.347m-15.482 0a50.636 50.636 0 0 0-2.658-.813A59.906 59.906 0 0 1 12 3.493a59.903 59.903 0 0 1 10.399 5.84c-.896.248-1.783.52-2.658.814m-15.482 0A50.717 50.717 0 0 1 12 13.489a50.702 50.702 0 0 1 7.74-3.342M6.75 15a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm0 0v-3.675A55.378 55.378 0 0 1 12 8.443m-7.007 11.55A5.981 5.981 0 0 0 6.75 15.75v-1.5" />
|
|
119
|
+
</svg>
|
|
120
|
+
|
|
121
|
+
<span>
|
|
122
|
+
Study
|
|
123
|
+
</span>
|
|
124
|
+
</div>
|
|
125
|
+
</wally-dropdown-menu-item>
|
|
126
|
+
<!-- <wally-dropdown-menu-item (click)="onItemClick()">
|
|
127
|
+
Privacidade
|
|
128
|
+
</wally-dropdown-menu-item> -->
|
|
129
|
+
</wally-dropdown-menu-sub-content>
|
|
130
|
+
</wally-dropdown-menu-sub>
|
|
131
|
+
</wally-dropdown-menu-group>
|
|
132
|
+
|
|
133
|
+
<!-- <wally-dropdown-menu-separator></wally-dropdown-menu-separator> -->
|
|
134
|
+
|
|
135
|
+
<!-- Item individual -->
|
|
136
|
+
<!-- <wally-dropdown-menu-item (click)="onItemClick()">
|
|
137
|
+
Sair
|
|
138
|
+
</wally-dropdown-menu-item> -->
|
|
139
|
+
</wally-dropdown-menu-content>
|
|
140
|
+
|
|
141
|
+
</wally-dropdown-menu>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<div>
|
|
145
|
+
<wally-button variant="ghost" [rounded]="true">
|
|
146
|
+
<div class="group flex items-center gap-2">
|
|
147
|
+
<div
|
|
148
|
+
class="max-w-0 group-hover:max-w-6 overflow-hidden transition-all duration-300 ease-in-out">
|
|
149
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
|
150
|
+
stroke="currentColor"
|
|
151
|
+
class="opacity-0 group-hover:opacity-100 transition-opacity duration-300 size-6 rounded-full p-0.5 bg-neutral-300/40 dark:bg-white/10"
|
|
152
|
+
aria-hidden="true">
|
|
153
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
|
|
154
|
+
</svg>
|
|
155
|
+
</div>
|
|
156
|
+
|
|
157
|
+
<svg class="size-5" viewBox="0 0 400 600" fill="none" xmlns="http://www.w3.org/2000/svg"
|
|
158
|
+
aria-hidden="true">
|
|
159
|
+
<path
|
|
160
|
+
d="M0 500C0 444.772 44.772 400 100 400H200V500C200 555.228 155.228 600 100 600C44.772 600 0 555.228 0 500Z"
|
|
161
|
+
fill="#24CB71" />
|
|
162
|
+
<path d="M200 0V200H300C355.228 200 400 155.228 400 100C400 44.772 355.228 0 300 0H200Z"
|
|
163
|
+
fill="#FF7237" />
|
|
164
|
+
<path
|
|
165
|
+
d="M299.167 400C354.395 400 399.167 355.228 399.167 300C399.167 244.772 354.395 200 299.167 200C243.939 200 199.167 244.772 199.167 300C199.167 355.228 243.939 400 299.167 400Z"
|
|
166
|
+
fill="#00B6FF" />
|
|
167
|
+
<path d="M0 100C0 155.228 44.772 200 100 200H200V0H100C44.772 0 0 44.772 0 100Z"
|
|
168
|
+
fill="#FF3737" />
|
|
169
|
+
<path d="M0 300C0 355.228 44.772 400 100 400H200V200H100C44.772 200 0 244.772 0 300Z"
|
|
170
|
+
fill="#874FFF" />
|
|
171
|
+
</svg>
|
|
172
|
+
|
|
173
|
+
<span class="text-base">Figma</span>
|
|
174
|
+
</div>
|
|
53
175
|
</wally-button>
|
|
54
|
-
</
|
|
176
|
+
</div>
|
|
55
177
|
</div>
|
|
56
178
|
|
|
57
|
-
<div class="size-10">
|
|
58
|
-
<
|
|
59
|
-
[
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
179
|
+
<div class="w-full size-10 flex gap-2 justify-end">
|
|
180
|
+
<div>
|
|
181
|
+
<wally-tooltip [text]="'Use voice input'" position="bottom">
|
|
182
|
+
<wally-button [variant]="'ghost'" [rounded]="true" [ariaLabel]="'Send message'">
|
|
183
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2"
|
|
184
|
+
stroke="currentColor" class="size-6">
|
|
185
|
+
<path stroke-linecap="round" stroke-linejoin="round"
|
|
186
|
+
d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z" />
|
|
187
|
+
</svg>
|
|
188
|
+
</wally-button>
|
|
189
|
+
</wally-tooltip>
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
<div>
|
|
193
|
+
<wally-button [variant]="'primary'" [rounded]="true" [ariaLabel]="'Send message'">
|
|
194
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="3"
|
|
195
|
+
stroke="currentColor" class="size-5" aria-hidden="true">
|
|
196
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18" />
|
|
197
|
+
</svg>
|
|
198
|
+
</wally-button>
|
|
199
|
+
</div>
|
|
67
200
|
</div>
|
|
68
201
|
</div>
|
|
69
202
|
</div>
|
|
@@ -1,19 +1,41 @@
|
|
|
1
1
|
import { Component } from '@angular/core';
|
|
2
2
|
|
|
3
|
+
import { DropdownMenuSubTrigger } from '../../dropdown-menu/dropdown-menu-sub-trigger/dropdown-menu-sub-trigger';
|
|
4
|
+
import { DropdownMenuSubContent } from '../../dropdown-menu/dropdown-menu-sub-content/dropdown-menu-sub-content';
|
|
5
|
+
import { DropdownMenuSeparator } from '../../dropdown-menu/dropdown-menu-separator/dropdown-menu-separator';
|
|
6
|
+
import { DropdownMenuTrigger } from '../../dropdown-menu/dropdown-menu-trigger/dropdown-menu-trigger';
|
|
7
|
+
import { DropdownMenuContent } from '../../dropdown-menu/dropdown-menu-content/dropdown-menu-content';
|
|
8
|
+
import { DropdownMenuLabel } from '../../dropdown-menu/dropdown-menu-label/dropdown-menu-label';
|
|
9
|
+
import { DropdownMenuGroup } from '../../dropdown-menu/dropdown-menu-group/dropdown-menu-group';
|
|
10
|
+
import { DropdownMenuItem } from '../../dropdown-menu/dropdown-menu-item/dropdown-menu-item';
|
|
11
|
+
import { DropdownMenuSub } from '../../dropdown-menu/dropdown-menu-sub/dropdown-menu-sub';
|
|
3
12
|
import { AiPromptInput } from '../ai-prompt-input/ai-prompt-input';
|
|
4
|
-
import {
|
|
13
|
+
import { DropdownMenu } from '../../dropdown-menu/dropdown-menu';
|
|
5
14
|
import { Tooltip } from '../../tooltip/tooltip';
|
|
15
|
+
import { Button } from '../../button/button';
|
|
6
16
|
|
|
7
17
|
@Component({
|
|
8
18
|
selector: 'wally-ai-composer',
|
|
9
19
|
imports: [
|
|
10
20
|
AiPromptInput,
|
|
11
21
|
Tooltip,
|
|
12
|
-
Button
|
|
22
|
+
Button,
|
|
23
|
+
DropdownMenu,
|
|
24
|
+
DropdownMenuTrigger,
|
|
25
|
+
DropdownMenuContent,
|
|
26
|
+
DropdownMenuItem,
|
|
27
|
+
DropdownMenuLabel,
|
|
28
|
+
DropdownMenuSeparator,
|
|
29
|
+
DropdownMenuGroup,
|
|
30
|
+
DropdownMenuSub,
|
|
31
|
+
DropdownMenuSubTrigger,
|
|
32
|
+
DropdownMenuSubContent
|
|
13
33
|
],
|
|
14
34
|
templateUrl: './ai-composer.html',
|
|
15
35
|
styleUrl: './ai-composer.css'
|
|
16
36
|
})
|
|
17
37
|
export class AiComposer {
|
|
18
|
-
|
|
38
|
+
onItemClick(): void {
|
|
39
|
+
console.log('Item clicked');
|
|
40
|
+
}
|
|
19
41
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<textarea #textarea id="ai-prompt-input" class="w-full h-auto max-h-
|
|
1
|
+
<textarea #textarea id="ai-prompt-input" class="w-full h-auto max-h-48 text-base placeholder:text-neutral-400 dark:text-white dark:placeholder:text-neutral-500 resize-none focus:outline-none focus:ring-0 overflow-y-auto [&::-webkit-scrollbar]:w-2
|
|
2
2
|
[&::-webkit-scrollbar-track]:bg-transparent
|
|
3
3
|
[&::-webkit-scrollbar-thumb]:bg-neutral-300
|
|
4
4
|
[&::-webkit-scrollbar-thumb]:rounded-full
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Component, computed, input, InputSignal, Signal } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
type Variant = 'default' | 'outline' | 'secondary' | 'destructive';
|
|
4
|
+
|
|
5
|
+
@Component({
|
|
6
|
+
selector: 'wally-badge',
|
|
7
|
+
imports: [],
|
|
8
|
+
templateUrl: './badge.html',
|
|
9
|
+
styleUrl: './badge.css'
|
|
10
|
+
})
|
|
11
|
+
export class Badge {
|
|
12
|
+
variant: InputSignal<Variant> = input<Variant>('default');
|
|
13
|
+
|
|
14
|
+
variantClasses: Signal<string> = computed(() => {
|
|
15
|
+
const variantMap: Record<Variant, string> = {
|
|
16
|
+
default: '#0a0a0a] hover:bg-[#0a0a0a]/85 disabled:bg-[#0a0a0a]/85 dark:text-[#0a0a0a] dark:bg-white dark:hover:bg-white/85 dark:disabled:bg-white/85 dark:disabled:text-[#0a0a0a]/60 shadow',
|
|
17
|
+
outline: '',
|
|
18
|
+
secondary: '',
|
|
19
|
+
destructive: ''
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
return variantMap[this.variant()] || variantMap.default;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
<button [type]="type()" [disabled]="disabled() || loading()" [attr.aria-label]="ariaLabel() || null"
|
|
2
2
|
[attr.aria-describedby]="ariaDescribedBy() || null" [attr.aria-pressed]="ariaPressed()" [attr.aria-busy]="loading()"
|
|
3
|
-
(click)="handleClick()"
|
|
4
|
-
[class]="'group relative w-full flex items-center justify-center gap-2 text-sm font-medium text-white disabled:pointer-events-none p-2.5 transition-all duration-300 ease-in-out antialiased cursor-pointer ' + variantClasses()"
|
|
5
|
-
[ngClass]="{
|
|
3
|
+
(click)="handleClick()" [class]="'group relative w-full flex items-center justify-center gap-2 text-sm font-medium text-white active:scale-95 disabled:pointer-events-none p-2.5 disabled:active:scale-100 transition-all duration-300 ease-in-out antialiased cursor-pointer ' + variantClasses()" [ngClass]="{
|
|
6
4
|
'rounded-md': !rounded(),
|
|
7
5
|
'rounded-full': rounded()
|
|
8
6
|
}">
|
|
@@ -33,10 +33,10 @@ export class Button {
|
|
|
33
33
|
// Computed classes based on variant
|
|
34
34
|
variantClasses: Signal<string> = computed(() => {
|
|
35
35
|
const variantMap: Record<ButtonVariant, string> = {
|
|
36
|
-
primary: 'bg-[#0a0a0a] hover:bg-[#0a0a0a]/85 disabled:bg-[#0a0a0a]/85 dark:text-[#0a0a0a] dark:bg-white dark:hover:bg-white/85 dark:disabled:bg-white/85 dark:disabled:text-[#0a0a0a]/60',
|
|
37
|
-
secondary: '!text-[#0a0a0a] bg-neutral-200 hover:bg-neutral-200/60 disabled:bg-neutral-200/80 disabled:!text-neutral-400 dark:!text-white dark:bg-white/20 dark:hover:bg-white/10 dark:disabled:bg-white/5 dark:disabled:text-white/50',
|
|
38
|
-
destructive: 'dark:text-white bg-red-500 hover:bg-red-500/80 disabled:bg-red-500/80 disabled:text-white/80 dark:disabled:text-white/60',
|
|
39
|
-
outline: '!text-[#0a0a0a] bg-transparent border border-neutral-400 hover:bg-neutral-200/60 disabled:!text-neutral-500 dark:!text-white dark:border-neutral-500 dark:bg-neutral-500/10 dark:hover:bg-neutral-500/20 dark:disabled:!text-white/60',
|
|
36
|
+
primary: 'bg-[#0a0a0a] hover:bg-[#0a0a0a]/85 disabled:bg-[#0a0a0a]/85 dark:text-[#0a0a0a] dark:bg-white dark:hover:bg-white/85 dark:disabled:bg-white/85 dark:disabled:text-[#0a0a0a]/60 shadow',
|
|
37
|
+
secondary: '!text-[#0a0a0a] bg-neutral-200 hover:bg-neutral-200/60 disabled:bg-neutral-200/80 disabled:!text-neutral-400 dark:!text-white dark:bg-white/20 dark:hover:bg-white/10 dark:disabled:bg-white/5 dark:disabled:text-white/50 shadow',
|
|
38
|
+
destructive: 'dark:text-white bg-red-500 hover:bg-red-500/80 disabled:bg-red-500/80 disabled:text-white/80 dark:disabled:text-white/60 shadow',
|
|
39
|
+
outline: '!text-[#0a0a0a] bg-transparent border border-neutral-400 hover:bg-neutral-200/60 disabled:!text-neutral-500 dark:!text-white dark:border-neutral-500 dark:bg-neutral-500/10 dark:hover:bg-neutral-500/20 dark:disabled:!text-white/60 shadow',
|
|
40
40
|
ghost: '!text-[#0a0a0a] bg-transparent hover:bg-neutral-100 disabled:!text-neutral-400 dark:!text-white dark:hover:bg-white/5 dark:disabled:!text-white/50',
|
|
41
41
|
link: '!text-blue-600 bg-transparent underline-offset-4 hover:underline disabled:!text-blue-400 dark:!text-blue-600 dark:hover:!text-blue-500 dark:disabled:!text-blue-400'
|
|
42
42
|
};
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
@if (dropdownMenuService.isOpen()) {
|
|
2
|
+
<div
|
|
3
|
+
(mouseenter)="onMouseEnter()"
|
|
4
|
+
(mouseleave)="onMouseLeave()"
|
|
5
|
+
[class]="'absolute bg-white dark:bg-[#1b1b1b] dark:border-neutral-700 rounded-xl shadow-2xl border border-neutral-300 min-w-72 z-50 transition-all duration-200 ease-out ' + positionClasses()"
|
|
6
|
+
role="menu">
|
|
7
|
+
<ng-content></ng-content>
|
|
8
|
+
</div>
|
|
9
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
|
|
3
|
+
import { DropdownMenuContent } from './dropdown-menu-content';
|
|
4
|
+
|
|
5
|
+
describe('DropdownMenuContent', () => {
|
|
6
|
+
let component: DropdownMenuContent;
|
|
7
|
+
let fixture: ComponentFixture<DropdownMenuContent>;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
await TestBed.configureTestingModule({
|
|
11
|
+
imports: [DropdownMenuContent]
|
|
12
|
+
})
|
|
13
|
+
.compileComponents();
|
|
14
|
+
|
|
15
|
+
fixture = TestBed.createComponent(DropdownMenuContent);
|
|
16
|
+
component = fixture.componentInstance;
|
|
17
|
+
fixture.detectChanges();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should create', () => {
|
|
21
|
+
expect(component).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { Component, computed, effect, ElementRef, input, signal } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
import { DropdownMenuService } from '../dropdown-menu.service';
|
|
4
|
+
|
|
5
|
+
export type DropdownPosition = 'bottom' | 'top' | 'left' | 'right';
|
|
6
|
+
|
|
7
|
+
@Component({
|
|
8
|
+
selector: 'wally-dropdown-menu-content',
|
|
9
|
+
imports: [],
|
|
10
|
+
templateUrl: './dropdown-menu-content.html',
|
|
11
|
+
styleUrl: './dropdown-menu-content.css'
|
|
12
|
+
})
|
|
13
|
+
export class DropdownMenuContent {
|
|
14
|
+
position = input<DropdownPosition>('bottom');
|
|
15
|
+
|
|
16
|
+
calculatedPosition = signal<DropdownPosition>('bottom');
|
|
17
|
+
|
|
18
|
+
positionClasses = computed(() => {
|
|
19
|
+
const position = this.calculatedPosition();
|
|
20
|
+
const scrollClasses = 'max-h-96 overflow-visible';
|
|
21
|
+
|
|
22
|
+
const positionMap = {
|
|
23
|
+
bottom: 'top-full mt-1 left-0',
|
|
24
|
+
top: 'bottom-full mb-1 left-0',
|
|
25
|
+
right: 'left-full ml-1 top-0',
|
|
26
|
+
left: 'right-full mr-1 top-0'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return `${scrollClasses} ${positionMap[position]}`;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
constructor(
|
|
33
|
+
public dropdownMenuService: DropdownMenuService,
|
|
34
|
+
private elementRef: ElementRef
|
|
35
|
+
) {
|
|
36
|
+
effect(() => {
|
|
37
|
+
if (this.dropdownMenuService.isOpen()) {
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
const bestPosition = this.calculateBestPosition();
|
|
40
|
+
this.calculatedPosition.set(bestPosition);
|
|
41
|
+
}, 0);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Measures available space around the trigger element in all directions.
|
|
48
|
+
* @returns Object containing trigger dimensions and available space, or null if trigger not found
|
|
49
|
+
*/
|
|
50
|
+
private measureAvailableSpace(): {
|
|
51
|
+
triggerRect: any;
|
|
52
|
+
spaceAbove: any;
|
|
53
|
+
spaceBelow: number;
|
|
54
|
+
spaceLeft: any;
|
|
55
|
+
spaceRight: number;
|
|
56
|
+
} | null {
|
|
57
|
+
const triggerElement = this.elementRef.nativeElement.parentElement;
|
|
58
|
+
|
|
59
|
+
if (!triggerElement) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const triggerRect = triggerElement.getBoundingClientRect();
|
|
64
|
+
const viewportWidth = window.innerWidth;
|
|
65
|
+
const viewportHeight = window.innerHeight;
|
|
66
|
+
|
|
67
|
+
const spaceAbove = triggerRect.top;
|
|
68
|
+
const spaceBelow = viewportHeight - triggerRect.bottom;
|
|
69
|
+
const spaceLeft = triggerRect.left;
|
|
70
|
+
const spaceRight = viewportWidth - triggerRect.right;
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
triggerRect,
|
|
74
|
+
spaceAbove,
|
|
75
|
+
spaceBelow,
|
|
76
|
+
spaceLeft,
|
|
77
|
+
spaceRight
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Calculates the best position for the dropdown based on available viewport space.
|
|
83
|
+
* Falls back to alternative positions if preferred position doesn't fit.
|
|
84
|
+
* @returns The optimal dropdown position
|
|
85
|
+
*/
|
|
86
|
+
private calculateBestPosition(): DropdownPosition {
|
|
87
|
+
const space = this.measureAvailableSpace();
|
|
88
|
+
|
|
89
|
+
if (!space) {
|
|
90
|
+
return this.position();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const menuDimensions = this.getMenuDimensions();
|
|
94
|
+
const MENU_MIN_HEIGHT = menuDimensions.height + 20;
|
|
95
|
+
const MENU_MIN_WIDTH = menuDimensions.width + 20;
|
|
96
|
+
|
|
97
|
+
const preferred = this.position();
|
|
98
|
+
|
|
99
|
+
switch (preferred) {
|
|
100
|
+
case 'bottom':
|
|
101
|
+
if (space.spaceBelow >= MENU_MIN_HEIGHT) return 'bottom';
|
|
102
|
+
if (space.spaceAbove >= MENU_MIN_HEIGHT) return 'top';
|
|
103
|
+
if (space.spaceRight >= MENU_MIN_WIDTH) return 'right';
|
|
104
|
+
return 'left';
|
|
105
|
+
|
|
106
|
+
case 'top':
|
|
107
|
+
if (space.spaceAbove >= MENU_MIN_HEIGHT) return 'top';
|
|
108
|
+
if (space.spaceBelow >= MENU_MIN_HEIGHT) return 'bottom';
|
|
109
|
+
if (space.spaceRight >= MENU_MIN_WIDTH) return 'right';
|
|
110
|
+
return 'left';
|
|
111
|
+
|
|
112
|
+
case 'right':
|
|
113
|
+
if (space.spaceRight >= MENU_MIN_WIDTH) return 'right';
|
|
114
|
+
if (space.spaceLeft >= MENU_MIN_WIDTH) return 'left';
|
|
115
|
+
if (space.spaceBelow >= MENU_MIN_HEIGHT) return 'bottom';
|
|
116
|
+
return 'top';
|
|
117
|
+
|
|
118
|
+
case 'left':
|
|
119
|
+
if (space.spaceLeft >= MENU_MIN_WIDTH) return 'left';
|
|
120
|
+
if (space.spaceRight >= MENU_MIN_WIDTH) return 'right';
|
|
121
|
+
if (space.spaceBelow >= MENU_MIN_HEIGHT) return 'bottom';
|
|
122
|
+
return 'top';
|
|
123
|
+
|
|
124
|
+
default:
|
|
125
|
+
return 'bottom';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private getMenuDimensions(): {
|
|
130
|
+
height: number;
|
|
131
|
+
width: number;
|
|
132
|
+
} {
|
|
133
|
+
const menuElement = this.elementRef.nativeElement.querySelector('[role="menu"]');
|
|
134
|
+
|
|
135
|
+
if (!menuElement) {
|
|
136
|
+
return {
|
|
137
|
+
height: 200,
|
|
138
|
+
width: 224
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const rect = menuElement.getBoundingClientRect();
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
height: rect.height || 200,
|
|
146
|
+
width: rect.width || 224
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
onMouseEnter(): void {
|
|
151
|
+
if (this.dropdownMenuService.triggerMode() === 'hover') {
|
|
152
|
+
this.dropdownMenuService.setHoveringContent(true);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
onMouseLeave(): void {
|
|
157
|
+
if (this.dropdownMenuService.triggerMode() === 'hover') {
|
|
158
|
+
this.dropdownMenuService.setHoveringContent(false);
|
|
159
|
+
|
|
160
|
+
setTimeout(() => {
|
|
161
|
+
if (!this.dropdownMenuService.isHoveringContent()) {
|
|
162
|
+
this.dropdownMenuService.close();
|
|
163
|
+
}
|
|
164
|
+
}, 100);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
|
|
3
|
+
import { DropdownMenuGroup } from './dropdown-menu-group';
|
|
4
|
+
|
|
5
|
+
describe('DropdownMenuGroup', () => {
|
|
6
|
+
let component: DropdownMenuGroup;
|
|
7
|
+
let fixture: ComponentFixture<DropdownMenuGroup>;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
await TestBed.configureTestingModule({
|
|
11
|
+
imports: [DropdownMenuGroup]
|
|
12
|
+
})
|
|
13
|
+
.compileComponents();
|
|
14
|
+
|
|
15
|
+
fixture = TestBed.createComponent(DropdownMenuGroup);
|
|
16
|
+
component = fixture.componentInstance;
|
|
17
|
+
fixture.detectChanges();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should create', () => {
|
|
21
|
+
expect(component).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
});
|