Skip to content

Commit 02db1f8

Browse files
authored
Merge branch 'master' into position
2 parents 79b13a4 + 12f9749 commit 02db1f8

File tree

11 files changed

+119
-299
lines changed

11 files changed

+119
-299
lines changed

package-lock.json

Lines changed: 54 additions & 49 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@
146146
"zone.js": "0.9.0"
147147
},
148148
"dependencies": {
149+
"@carbon/utils-position": "1.0.0",
149150
"flatpickr": "4.5.7",
150151
"ng2-flatpickr": "7.0.3"
151152
}

src/dialog/dialog.component.ts

Lines changed: 9 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
} from "rxjs";
1919
import { throttleTime } from "rxjs/operators";
2020
// the AbsolutePosition is required to import the declaration correctly
21-
import position, { AbsolutePosition } from "./../utils/position";
21+
import { position, AbsolutePosition } from "@carbon/utils-position";
2222
import { cycleTabs, getFocusElementList } from "./../common/tab.service";
2323
import { DialogConfig } from "./dialog-config.interface";
2424

@@ -40,63 +40,46 @@ import { DialogConfig } from "./dialog-config.interface";
4040
export class Dialog implements OnInit, AfterViewInit, OnDestroy {
4141
/**
4242
* One static event observable to handle window resizing.
43-
* @protected
44-
* @static
45-
* @type {Observable<any>}
46-
* @memberof Dialog
4743
*/
4844
protected static resizeObservable: Observable<any> = fromEvent(window, "resize").pipe(throttleTime(100));
4945
/**
5046
* Emits event that handles the closing of a `Dialog` object.
51-
* @type {EventEmitter<any>}
52-
* @memberof Dialog
5347
*/
5448
@Output() close: EventEmitter<any> = new EventEmitter();
5549
/**
5650
* Receives `DialogConfig` interface object with properties of `Dialog`
57-
* explictly defined.
58-
* @type {DialogConfig}
59-
* @memberof Dialog
51+
* explicitly defined.
6052
*/
6153
@Input() dialogConfig: DialogConfig;
6254
/**
6355
* Maintains a reference to the view DOM element of the `Dialog`.
64-
* @type {ElementRef}
65-
* @memberof Dialog
6656
*/
6757
@ViewChild("dialog") dialog: ElementRef;
6858

6959
/**
7060
* Stores the data received from `dialogConfig`.
71-
* @memberof Dialog
7261
*/
7362
public data = {};
7463

7564
/**
76-
* The placement of the `Dialog` is recieved from the `Position` service.
77-
* @type {Placement}
78-
* @memberof Dialog
65+
* The placement of the `Dialog` is received from the `Position` service.
7966
*/
8067
public placement: string;
8168

8269
/**
8370
* `Subscription` used to update placement in the event of a window resize.
84-
* @protected
85-
* @type {Subscription}
86-
* @memberof Dialog
8771
*/
8872
protected resizeSubscription: Subscription;
8973
/**
9074
* Subscription to all the scrollable parents `scroll` event
9175
*/
92-
// add a new subscription temprarily so that contexts (such as tests)
76+
// add a new subscription temporarily so that contexts (such as tests)
9377
// that don't run ngAfterViewInit have something to unsubscribe in ngOnDestroy
9478
protected scrollSubscription: Subscription = new Subscription();
9579
/**
9680
* Handles offsetting the `Dialog` item based on the defined position
9781
* to not obscure the content beneath.
9882
* @protected
99-
* @memberof Dialog
10083
*/
10184
protected addGap = {
10285
"left": pos => position.addOffset(pos, 0, -this.dialogConfig.gap),
@@ -110,13 +93,11 @@ export class Dialog implements OnInit, AfterViewInit, OnDestroy {
11093
/**
11194
* Creates an instance of `Dialog`.
11295
* @param {ElementRef} elementRef
113-
* @memberof Dialog
11496
*/
115-
constructor(protected elementRef: ElementRef) {}
97+
constructor(protected elementRef: ElementRef) { }
11698

11799
/**
118-
* Initilize the `Dialog`, set the placement and gap, and add a `Subscription` to resize events.
119-
* @memberof Dialog
100+
* Initialize the `Dialog`, set the placement and gap, and add a `Subscription` to resize events.
120101
*/
121102
ngOnInit() {
122103
this.placement = this.dialogConfig.placement.split(",")[0];
@@ -126,14 +107,13 @@ export class Dialog implements OnInit, AfterViewInit, OnDestroy {
126107
this.placeDialog();
127108
});
128109

129-
// run any additional initlization code that consuming classes may have
110+
// run any additional initialization code that consuming classes may have
130111
this.onDialogInit();
131112
}
132113

133114
/**
134115
* After the DOM is ready, focus is set and dialog is placed
135116
* in respect to the parent element.
136-
* @memberof Dialog
137117
*/
138118
ngAfterViewInit() {
139119
const dialogElement = this.dialog.nativeElement;
@@ -236,30 +216,9 @@ export class Dialog implements OnInit, AfterViewInit, OnDestroy {
236216
// split always returns an array, so we can just use the auto position logic
237217
// for single positions too
238218
const placements = this.dialogConfig.placement.split(",");
239-
const weightedPlacements = placements.map(placement => {
240-
const pos = findPosition(parentEl, el, placement);
241-
let box = position.getPlacementBox(el, pos);
242-
let hiddenHeight = box.bottom - window.innerHeight - window.scrollY;
243-
let hiddenWidth = box.right - window.innerWidth - window.scrollX;
244-
// if the hiddenHeight or hiddenWidth is negative, reset to offsetHeight or offsetWidth
245-
hiddenHeight = hiddenHeight < 0 ? el.offsetHeight : hiddenHeight;
246-
hiddenWidth = hiddenWidth < 0 ? el.offsetWidth : hiddenWidth;
247-
const area = el.offsetHeight * el.offsetWidth;
248-
const hiddenArea = hiddenHeight * hiddenWidth;
249-
let visibleArea = area - hiddenArea;
250-
// if the visibleArea is 0 set it back to area (to calculate the percentage in a useful way)
251-
visibleArea = visibleArea === 0 ? area : visibleArea;
252-
const visiblePercent = visibleArea / area;
253-
return {
254-
placement,
255-
weight: visiblePercent
256-
};
257-
});
258219

259-
// sort the placements from best to worst
260-
weightedPlacements.sort((a, b) => b.weight - a.weight);
261-
// pick the best!
262-
dialogPlacement = weightedPlacements[0].placement;
220+
// find the best placement
221+
dialogPlacement = position.findBestPlacement(parentEl, el, placements);
263222

264223
// calculate the final position
265224
const pos = findPosition(parentEl, el, dialogPlacement);
@@ -293,7 +252,6 @@ export class Dialog implements OnInit, AfterViewInit, OnDestroy {
293252
* Sets up a event Listener to close `Dialog` if click event occurs outside
294253
* `Dialog` object.
295254
* @param {any} event
296-
* @memberof Dialog
297255
*/
298256
@HostListener("document:click", ["$event"])
299257
clickClose(event) {
@@ -305,15 +263,13 @@ export class Dialog implements OnInit, AfterViewInit, OnDestroy {
305263

306264
/**
307265
* Closes `Dialog` object by emitting the close event upwards to parents.
308-
* @memberof Dialog
309266
*/
310267
public doClose() {
311268
this.close.emit();
312269
}
313270

314271
/**
315272
* At destruction of component, `Dialog` unsubscribes from handling window resizing changes.
316-
* @memberof Dialog
317273
*/
318274
ngOnDestroy() {
319275
this.resizeSubscription.unsubscribe();

src/dialog/overflow-menu/overflow-menu-pane.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Component, HostListener, ElementRef, AfterViewInit } from "@angular/core";
22
import { Dialog } from "../dialog.component";
3-
import { position } from "../../utils/position";
3+
import { position } from "@carbon/utils-position";
44
import { isFocusInLastItem, isFocusInFirstItem } from "./../../common/tab.service";
55
import { I18n } from "./../../i18n/i18n.module";
66
import { ExperimentalService } from "./../../experimental.module";

src/dialog/overflow-menu/overflow-menu.stories.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ storiesOf("Overflow Menu", module)
4848
}))
4949
.add("With links", () => ({
5050
template: `
51-
<app-experimental-component></app-experimental-component>
5251
<ibm-overflow-menu [flip]="flip" >
5352
<ibm-overflow-menu-option href="https://www.ibm.com" (selected)="selected($event)" (click)="click($event)">
5453
An example option that is really long to show what should be done to handle long text
@@ -57,7 +56,9 @@ storiesOf("Overflow Menu", module)
5756
<ibm-overflow-menu-option href="https://www.ibm.com" (selected)="selected($event)">Option 3</ibm-overflow-menu-option>
5857
<ibm-overflow-menu-option href="https://www.ibm.com" (selected)="selected($event)">Option 4</ibm-overflow-menu-option>
5958
<ibm-overflow-menu-option href="https://www.ibm.com" disabled="true" (selected)="selected($event)">Disabled</ibm-overflow-menu-option>
60-
<ibm-overflow-menu-option href="https://www.ibm.com" type="danger" (selected)="selected($event)">Danger option</ibm-overflow-menu-option>
59+
<ibm-overflow-menu-option href="https://www.ibm.com" type="danger" (selected)="selected($event)">
60+
Danger option
61+
</ibm-overflow-menu-option>
6162
</ibm-overflow-menu>
6263
<ibm-placeholder></ibm-placeholder>
6364
`,

src/dropdown/dropdown.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { NG_VALUE_ACCESSOR } from "@angular/forms";
1717
import { Observable, fromEvent, of, Subscription } from "rxjs";
1818

1919
import { AbstractDropdownView } from "./abstract-dropdown-view.class";
20-
import { position } from "../utils/position";
20+
import { position } from "@carbon/utils-position";
2121
import { I18n } from "./../i18n/i18n.module";
2222
import { ListItem } from "./list-item.interface";
2323
import { DropdownService } from "./dropdown.service";

src/dropdown/dropdown.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Injectable, ElementRef } from "@angular/core";
22
import { PlaceholderService } from "./../placeholder/placeholder.module";
33
import { fromEvent, Subscription } from "rxjs";
44
import { throttleTime } from "rxjs/operators";
5-
import position from "./../utils/position";
5+
import { position } from "@carbon/utils-position";
66

77
const defaultOffset = { top: 0, left: 0 };
88

src/timepicker-select/timepicker-select.component.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { Component, Input, ChangeDetectorRef, Output, EventEmitter, HostBinding } from "@angular/core";
1+
import {
2+
Component,
3+
Input,
4+
Output,
5+
EventEmitter,
6+
HostBinding
7+
} from "@angular/core";
28
import { Select } from "../select/select.component";
39

410
@Component({
@@ -20,15 +26,27 @@ export class TimePickerSelect extends Select {
2026
@HostBinding("class.bx--select") timeSelect = true;
2127
@HostBinding("class.bx--time-picker__select") timePickerSelect = true;
2228

29+
@Input() id = `timepicker-select-${TimePickerSelect.selectCount++}`;
30+
31+
/**
32+
* Set to true for a loading select.
33+
*/
34+
@Input() skeleton = false;
35+
36+
/**
37+
* `light` or `dark` select theme
38+
*/
39+
@Input() theme: "light" | "dark" = "dark";
40+
2341
@HostBinding("class.bx--skeleton") timePickerSelectSkeleton = this.skeleton;
24-
@HostBinding("class.bx--select--light") timePickerSelectLight = (true ? this.theme === "light" : false);
2542

26-
@Input() id = `timepicker-select-${TimePickerSelect.selectCount++}`;
43+
@HostBinding("class.bx--select--light") get timePickerSelectLight() {
44+
return this.theme === "light";
45+
}
2746

2847
@Output() valueChange: EventEmitter<string> = new EventEmitter();
2948

3049
onChange(event) {
3150
this.valueChange.emit(event.target.value);
32-
console.log(this.theme);
3351
}
3452
}

src/timepicker/timepicker.component.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@ import {
99
@Component({
1010
selector: "ibm-timepicker",
1111
template: `
12-
<div
13-
[ngClass]="{
14-
'bx--select--light': theme === 'light',
15-
'bx--skeleton': skeleton
16-
}"
17-
class="bx--time-picker__input">
12+
<div class="bx--time-picker__input">
1813
<label *ngIf="!skeleton" [attr.for]="id" class="bx--label">{{label}}</label>
1914
<input
15+
[ngClass]="{
16+
'bx--text-input--light': theme === 'light',
17+
'bx--skeleton': skeleton
18+
}"
2019
[value]="value"
2120
[placeholder]="placeholder"
2221
[pattern]="pattern"
@@ -45,6 +44,16 @@ export class TimePicker {
4544
@Input() disabled = false;
4645
@Input() value: string;
4746

47+
/**
48+
* Set to true for a loading select.
49+
*/
50+
@Input() skeleton = false;
51+
52+
/**
53+
* `light` or `dark` select theme
54+
*/
55+
@Input() theme: "light" | "dark" = "dark";
56+
4857
@Output() valueChange: EventEmitter<string> = new EventEmitter();
4958

5059
onChange(event) {

src/timepicker/timepicker.stories.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import { action } from "@storybook/addon-actions";
22
import { TimePickerSelectModule } from "../timepicker-select/timepicker-select.module";
33
import { TimePickerModule } from "./timepicker.module";
44
import { storiesOf, moduleMetadata } from "@storybook/angular";
5-
import { withKnobs, boolean, text } from "@storybook/addon-knobs/angular";
5+
import {
6+
withKnobs,
7+
boolean,
8+
text,
9+
select
10+
} from "@storybook/addon-knobs/angular";
611
import { ExperimentalModule } from "..";
712

813
storiesOf("Time Picker", module)
@@ -18,12 +23,12 @@ storiesOf("Time Picker", module)
1823
.addDecorator(withKnobs)
1924
.add("Simple", () => ({
2025
template: `
21-
<ibm-timepicker (valueChange)="timePickerChange($event)" [value]="value" [disabled]="disableTime" label="Select a time">
22-
<ibm-timepicker-select (valueChange)="timePickerSelectChange($event)" [disabled]="disabledSelect" display="inline">
26+
<ibm-timepicker [theme]="theme" (valueChange)="timePickerChange($event)" [value]="value" [disabled]="disableTime" label="Select a time">
27+
<ibm-timepicker-select [theme]="theme" (valueChange)="timePickerSelectChange($event)" [disabled]="disabledSelect" display="inline">
2328
<option selected value="AM">AM</option>
2429
<option value="PM">PM</option>
2530
</ibm-timepicker-select>
26-
<ibm-timepicker-select (valueChange)="timePickerSelectChange($event)" [disabled]="disabledSelect" display="inline">
31+
<ibm-timepicker-select [theme]="theme" (valueChange)="timePickerSelectChange($event)" [disabled]="disabledSelect" display="inline">
2732
<option selected value="Time Zone 1">Time Zone 1</option>
2833
<option value="Time Zone 2">Time Zone 2</option>
2934
</ibm-timepicker-select>
@@ -35,6 +40,7 @@ storiesOf("Time Picker", module)
3540
timePickerSelectChange: action("Time picker select change fired"),
3641
value: text("Time in 12hr format", "12:12"),
3742
disableTime: boolean("disabled time", false),
38-
disabledSelect: boolean("disabled selects", false)
43+
disabledSelect: boolean("disabled selects", false),
44+
theme: select("Theme", ["dark", "light"], "dark")
3945
}
4046
}));

0 commit comments

Comments
 (0)