Skip to content

Commit 32061ef

Browse files
committed
🔧 Replace storybook with custom storybook.
1 parent 45f92b0 commit 32061ef

File tree

10 files changed

+391
-37
lines changed

10 files changed

+391
-37
lines changed

example/lib/main.dart

Lines changed: 228 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1+
import 'dart:math';
2+
3+
import 'package:adaptive_theme/adaptive_theme.dart';
4+
import 'package:flutter/material.dart';
5+
import 'package:flutter/scheduler.dart';
6+
import 'package:flutter/services.dart';
7+
import 'package:flutter_box_transform/flutter_box_transform.dart';
18
import 'package:hyper_effects_demo/stories/color_filter_scroll_transition.dart';
2-
import 'package:hyper_effects_demo/stories/windows_settings_transition.dart';
39
import 'package:hyper_effects_demo/stories/scroll_phase_transition.dart';
10+
import 'package:hyper_effects_demo/stories/scroll_wheel_blur.dart';
411
import 'package:hyper_effects_demo/stories/scroll_wheel_transition.dart';
5-
import 'package:flutter/material.dart';
6-
import 'package:storybook_flutter/storybook_flutter.dart';
12+
import 'package:hyper_effects_demo/stories/windows_settings_transition.dart';
713

8-
import 'stories/scroll_wheel_blur.dart';
14+
import 'story.dart';
915

1016
void main() {
1117
runApp(const MyApp());
@@ -16,40 +22,229 @@ class MyApp extends StatelessWidget {
1622

1723
@override
1824
Widget build(BuildContext context) {
19-
return MaterialApp(
20-
title: 'Hyper Effects Story Book',
21-
debugShowCheckedModeBanner: false,
22-
home: Storybook(
23-
initialStory: 'Scroll Phase Offset',
24-
stories: [
25-
Story(
26-
name: 'Scroll Phase Offset',
27-
description: 'Offsetting elements based on the phase of the scroll.',
28-
builder: (context) => const ScrollPhaseTransition(),
29-
),
30-
Story(
31-
name: 'Scroll Phase Color Filter Transition',
32-
description: 'Blending and changing image colors based on scroll phase.',
33-
builder: (context) => const ColorFilterScrollTransition(),
25+
return AdaptiveTheme(
26+
light: ThemeData(
27+
useMaterial3: true,
28+
brightness: Brightness.light,
29+
colorSchemeSeed: Colors.blue,
30+
inputDecorationTheme: InputDecorationTheme(
31+
isDense: true,
32+
contentPadding:
33+
const EdgeInsets.symmetric(horizontal: 10, vertical: 12),
34+
border: OutlineInputBorder(
35+
borderRadius: BorderRadius.circular(6),
3436
),
35-
Story(
36-
name: 'Scroll Wheel Transition',
37-
description: 'Warping elements to mimic a cylindrical effect.',
38-
builder: (context) => const ScrollWheelTransition(),
39-
),
40-
Story(
41-
name: 'Scroll Phase Blur',
42-
description:
43-
'A focus effect where elements outside the view are blurred',
44-
builder: (context) => const ScrollWheelBlurTransition(),
37+
),
38+
),
39+
dark: ThemeData(
40+
useMaterial3: true,
41+
brightness: Brightness.dark,
42+
colorSchemeSeed: Colors.blue,
43+
inputDecorationTheme: InputDecorationTheme(
44+
isDense: true,
45+
contentPadding:
46+
const EdgeInsets.symmetric(horizontal: 10, vertical: 12),
47+
border: OutlineInputBorder(
48+
borderRadius: BorderRadius.circular(6),
4549
),
46-
Story(
47-
name: 'Pointer Transition',
48-
description: 'Moves elements slightly with the pointer',
49-
builder: (context) => const WindowsSettingsTransition(),
50+
),
51+
),
52+
initial: AdaptiveThemeMode.system,
53+
builder: (theme, darkTheme) => MaterialApp(
54+
title: 'Hyper Effects Storyboard',
55+
debugShowCheckedModeBanner: false,
56+
theme: theme,
57+
darkTheme: darkTheme,
58+
home: const Storyboard(),
59+
),
60+
);
61+
}
62+
}
63+
64+
class Storyboard extends StatefulWidget {
65+
const Storyboard({super.key});
66+
67+
@override
68+
State<Storyboard> createState() => _StoryboardState();
69+
}
70+
71+
class _StoryboardState extends State<Storyboard> {
72+
final List<Story> stories = [
73+
const Story(
74+
title: 'Scroll Phase Transition',
75+
child: ScrollPhaseTransition(),
76+
),
77+
const Story(
78+
title: 'Scroll Wheel Blur Transition',
79+
child: ScrollWheelBlurTransition(),
80+
),
81+
const Story(
82+
title: 'Scroll Wheel Transition',
83+
child: ScrollWheelTransition(),
84+
),
85+
const Story(
86+
title: 'Windows Settings Effect',
87+
child: WindowsSettingsTransition(),
88+
),
89+
const Story(
90+
title: 'Color Filter Scroll Transition',
91+
child: ColorFilterScrollTransition(),
92+
),
93+
];
94+
int? selectedStory;
95+
96+
void onStorySelected(int index) {
97+
setState(() {
98+
selectedStory = index;
99+
});
100+
}
101+
102+
@override
103+
Widget build(BuildContext context) {
104+
return Scaffold(
105+
body: Row(
106+
children: [
107+
SizedBox(
108+
width: 300,
109+
child: ListView(
110+
children: [
111+
for (final Story story in stories)
112+
ListTile(
113+
title: Text(story.title),
114+
onTap: () => onStorySelected(stories.indexOf(story)),
115+
selected: stories.indexOf(story) == selectedStory,
116+
),
117+
],
118+
),
50119
),
120+
const VerticalDivider(width: 2),
121+
Expanded(
122+
flex: 3,
123+
child: ContentView(
124+
child: AnimatedSwitcher(
125+
duration: const Duration(milliseconds: 300),
126+
child: selectedStory != null
127+
? stories[selectedStory!].child
128+
: const Center(
129+
child: Text('Select a story to view.'),
130+
),
131+
),
132+
)),
51133
],
52134
),
53135
);
54136
}
55137
}
138+
139+
class ContentView extends StatefulWidget {
140+
final Widget child;
141+
142+
const ContentView({super.key, required this.child});
143+
144+
@override
145+
State<ContentView> createState() => _ContentViewState();
146+
}
147+
148+
class _ContentViewState extends State<ContentView> with WidgetsBindingObserver {
149+
final GlobalKey _key = GlobalKey();
150+
151+
final TransformableBoxController controller = TransformableBoxController(
152+
resizeModeResolver: () {
153+
final pressedKeys = WidgetsBinding.instance.keyboard.logicalKeysPressed;
154+
155+
final isShiftPressed =
156+
pressedKeys.contains(LogicalKeyboardKey.shiftLeft) ||
157+
pressedKeys.contains(LogicalKeyboardKey.shiftRight);
158+
159+
if (isShiftPressed) {
160+
return ResizeMode.symmetricScale;
161+
} else {
162+
return ResizeMode.symmetric;
163+
}
164+
},
165+
allowFlippingWhileResizing: false,
166+
);
167+
168+
@override
169+
void initState() {
170+
super.initState();
171+
172+
controller
173+
.setConstraints(const BoxConstraints(minHeight: 200, minWidth: 200));
174+
175+
SchedulerBinding.instance.addPostFrameCallback((_) {
176+
controller.setClampingRect(getArea(), notify: false);
177+
controller.setRect(controller.clampingRect);
178+
if (mounted) setState(() {});
179+
});
180+
181+
WidgetsBinding.instance.addObserver(this);
182+
}
183+
184+
@override
185+
void didChangeMetrics() {
186+
super.didChangeMetrics();
187+
188+
controller.setClampingRect(getArea());
189+
controller.setRect(getRect(), recalculate: true);
190+
191+
if (mounted) setState(() {});
192+
}
193+
194+
@override
195+
void didUpdateWidget(covariant ContentView oldWidget) {
196+
super.didUpdateWidget(oldWidget);
197+
198+
controller.setRect(getRect(), recalculate: true);
199+
}
200+
201+
Rect getArea() {
202+
final RenderBox renderBox =
203+
_key.currentContext?.findRenderObject() as RenderBox;
204+
final size = renderBox.size;
205+
return Rect.fromLTWH(0, 0, size.width, size.height).deflate(16);
206+
}
207+
208+
Rect getRect() {
209+
Rect rect = controller.rect;
210+
rect = Rect.fromCenter(
211+
center: controller.clampingRect.center,
212+
width: min(controller.clampingRect.width, rect.width),
213+
height: min(controller.clampingRect.height, rect.height),
214+
);
215+
return rect;
216+
}
217+
218+
@override
219+
void dispose() {
220+
WidgetsBinding.instance.removeObserver(this);
221+
controller.dispose();
222+
super.dispose();
223+
}
224+
225+
@override
226+
Widget build(BuildContext context) {
227+
return Stack(
228+
key: _key,
229+
children: [
230+
TransformableBox(
231+
controller: controller,
232+
draggable: false,
233+
allowContentFlipping: false,
234+
contentBuilder: (BuildContext context, Rect rect, Flip flip) {
235+
return DecoratedBox(
236+
decoration: BoxDecoration(
237+
border: Border.all(
238+
color: Theme.of(context).colorScheme.primary,
239+
width: 2,
240+
strokeAlign: BorderSide.strokeAlignOutside,
241+
),
242+
),
243+
child: Center(child: widget.child),
244+
);
245+
},
246+
),
247+
],
248+
);
249+
}
250+
}

example/lib/stories/windows_settings_transition.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ class _WindowsSettingsTransitionState extends State<WindowsSettingsTransition> {
1414
Widget build(BuildContext context) {
1515
return Center(
1616
child: GridView.builder(
17-
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
18-
crossAxisCount: 3,
17+
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
18+
maxCrossAxisExtent: 200,
1919
crossAxisSpacing: 4,
2020
mainAxisSpacing: 4,
2121
),

example/lib/story.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import 'package:flutter/material.dart';
2+
3+
class Story {
4+
final String title;
5+
final Widget child;
6+
7+
const Story({
8+
required this.title,
9+
required this.child,
10+
});
11+
12+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
12
#include "ephemeral/Flutter-Generated.xcconfig"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
12
#include "ephemeral/Flutter-Generated.xcconfig"

example/macos/Flutter/GeneratedPluginRegistrant.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import FlutterMacOS
66
import Foundation
77

8+
import shared_preferences_foundation
89

910
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
11+
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
1012
}

example/macos/Podfile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
platform :osx, '10.14'
2+
3+
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
4+
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
5+
6+
project 'Runner', {
7+
'Debug' => :debug,
8+
'Profile' => :release,
9+
'Release' => :release,
10+
}
11+
12+
def flutter_root
13+
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
14+
unless File.exist?(generated_xcode_build_settings_path)
15+
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
16+
end
17+
18+
File.foreach(generated_xcode_build_settings_path) do |line|
19+
matches = line.match(/FLUTTER_ROOT\=(.*)/)
20+
return matches[1].strip if matches
21+
end
22+
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
23+
end
24+
25+
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
26+
27+
flutter_macos_podfile_setup
28+
29+
target 'Runner' do
30+
use_frameworks!
31+
use_modular_headers!
32+
33+
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
34+
target 'RunnerTests' do
35+
inherit! :search_paths
36+
end
37+
end
38+
39+
post_install do |installer|
40+
installer.pods_project.targets.each do |target|
41+
flutter_additional_macos_build_settings(target)
42+
end
43+
end

0 commit comments

Comments
 (0)